使用ElementTree读取XML表格时部分单元格数据无法读取求解决
问题分析
你的代码读取失败主要有两个核心原因:
- 命名空间不匹配:第四个单元格里的
<ss:Data>标签被重新指定了html命名空间(xmlns="http://www.w3.org/TR/REC-html40"),你用原ss命名空间的Data标签去查找,根本找不到这个元素,自然返回None。 - 文本嵌套在子元素中:就算找到了这个
Data元素,它的文本内容不是直接在Data节点下,而是嵌套在<Font>子元素里,直接用.text只能获取节点的直接文本,取不到子元素里的内容。
修复后的代码
我们需要添加html命名空间的处理,调整元素查找逻辑,同时递归提取所有子元素的文本:
from xml.etree import ElementTree import io xmlf = """<?xml version="1.0"?> <?mso-application progid="Excel.Sheet"?> <Workbook ss:ResourcesPackageName="" ss:ResourcesPackageVersion="" xmlns="urn:schemas-microsoft-com:office:spreadsheet" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" xmlns:html="http://www.w3.org/TR/REC-html40"> <Worksheet ss:Name="DigitalOutput" ss:IsDeviceType="true"> <Row ss:AutoFitHeight="0"> <Cell><Data ss:Type="String">A</Data><NamedCell ss:Name="_FilterDatabase"/></Cell> <Cell><Data ss:Type="String">B</Data><NamedCell ss:Name="_FilterDatabase"/></Cell> <Cell><Data ss:Type="String">C</Data><NamedCell ss:Name="_FilterDatabase"/></Cell> <Cell ss:Index="7"><ss:Data ss:Type="String" xmlns="http://www.w3.org/TR/REC-html40"><Font html:Color="#000000">CAN'T READ </Font><Font>THIS</Font></ss:Data><NamedCell ss:Name="_FilterDatabase"/></Cell> <Cell ss:Index="10"><Data ss:Type="String">D</Data><NamedCell ss:Name="_FilterDatabase"/></Cell> </Row> </Worksheet> </Workbook>""" # 定义用到的命名空间 ss = "urn:schemas-microsoft-com:office:spreadsheet" html_ns = "http://www.w3.org/TR/REC-html40" worksheet_label = '{%s}Worksheet' % ss row_label = '{%s}Row' % ss cell_label = '{%s}Cell' % ss data_label_ss = '{%s}Data' % ss data_label_html = '{%s}Data' % html_ns def get_all_text(element): """递归提取元素及其所有子元素的文本内容""" text = element.text or "" for child in element: text += get_all_text(child) if child.tail: text += child.tail return text.strip() tree = ElementTree.parse(io.StringIO(xmlf)) root = tree.getroot() for ws in root.findall(worksheet_label): for table in ws.findall(row_label): for c in table.findall(cell_label): # 先找ss命名空间的Data data = c.find(data_label_ss) # 如果找不到,再找html命名空间的Data if data is None: data = c.find(data_label_html) # 提取所有文本内容 if data is not None: print(get_all_text(data)) else: print("No data found")
代码说明
- 命名空间兼容:新增了
html_ns变量,当找不到ss命名空间的Data时,自动尝试查找html命名空间的Data元素,覆盖了特殊单元格的情况。 - 递归文本提取:
get_all_text函数会递归遍历所有子元素,把分散在<Font>标签里的文本拼接成完整内容,解决了嵌套文本的读取问题。
运行这段代码后,输出会变成:
A B C CAN'T READ THIS D
内容的提问来源于stack exchange,提问作者rafasan
相关产品推荐
相关产品推荐

