如何用Python读取后缀为.xls的XML电子表格并指定目标工作表
读取后缀为.xls的XML Spreadsheet并指定工作表的Python解决方案
问题背景
有一个后缀为.xls但实际是XML Spreadsheet格式的文件,包含3个工作表,需要读取名为sheetname3的工作表数据。以下是针对你尝试过的两种方法的修正方案:
方法一:用pandas直接解析XML(推荐)
pd.read_excel搭配openpyxl引擎无法识别XML Spreadsheet格式(openpyxl仅支持.xlsx及标准二进制.xls文件),改用pd.read_xml直接解析XML结构,通过XPath精准定位目标工作表:
import pandas as pd import os DATE = "你的日期变量值" # 替换为实际日期 kpath = os.path.join(r"F:\DOCUMENT\Treasury\Test\K vs Clearer", f'REC_IRSOIS_{DATE}.xls') # 定位到名称为sheetname3的工作表数据区域 df = pd.read_xml( kpath, xpath="//Worksheet[Name/text()='sheetname3']/Table" ) # 若第一行是表头,添加header=0参数 df = pd.read_xml( kpath, xpath="//Worksheet[Name/text()='sheetname3']/Table", header=0 )
原理
XML Spreadsheet的结构中,每个工作表对应<Worksheet>节点,其下的<Name>子节点存储工作表名称,数据则在<Table>节点内。通过XPath表达式可直接筛选出目标工作表的数据区域。
方法二:改进自定义SAX解析器,支持指定工作表
原SAX解析器未区分工作表名称,改进后会先识别工作表名称,仅收集目标工作表的数据:
from xml.sax import make_parser, ContentHandler import pandas as pd import os class ExcelHandler(ContentHandler): def __init__(self, target_sheet): self.target_sheet = target_sheet self.current_sheet = None self.in_name_tag = False self.chars_buffer = [] self.current_row = [] self.sheet_rows = [] self.target_data = None def characters(self, content): if self.in_name_tag: self.chars_buffer.append(content) elif self.current_sheet == self.target_sheet: self.chars_buffer.append(content) def startElement(self, name, atts): if name == "Name": self.in_name_tag = True self.chars_buffer = [] elif name == "Cell" and self.current_sheet == self.target_sheet: self.chars_buffer = [] elif name == "Row" and self.current_sheet == self.target_sheet: self.current_row = [] elif name == "Table" and self.current_sheet == self.target_sheet: self.sheet_rows = [] def endElement(self, name): if name == "Name": self.current_sheet = ''.join(self.chars_buffer).strip() self.in_name_tag = False elif name == "Cell" and self.current_sheet == self.target_sheet: self.current_row.append(''.join(self.chars_buffer)) elif name == "Row" and self.current_sheet == self.target_sheet: self.sheet_rows.append(self.current_row.copy()) elif name == "Table" and self.current_sheet == self.target_sheet: self.target_data = self.sheet_rows.copy() # 使用示例 DATE = "你的日期变量值" kpath = os.path.join(r"F:\DOCUMENT\Treasury\Test\K vs Clearer", f'REC_IRSOIS_{DATE}.xls') target_sheet_name = "sheetname3" parser = make_parser() handler = ExcelHandler(target_sheet_name) parser.setContentHandler(handler) parser.parse(kpath) # 将目标数据转为DataFrame(假设第一行是表头) df = pd.DataFrame(handler.target_data[1:], columns=handler.target_data[0])
原理
改进后的解析器会先读取每个<Worksheet>的<Name>节点,记录当前工作表名称;只有当名称匹配目标时,才开始收集<Table>节点下的行和单元格数据,最终将目标工作表的数据存储在target_data属性中。
内容的提问来源于stack exchange,提问作者Raj Das
相关产品推荐
相关产品推荐

