pandas的read_xml无法处理多层嵌套xml,因其仅提取record直接子元素;应使用xml.etree.elementtree手动遍历,通过find('.//tag')跨层查找并用iterparse流式解析大文件。

Pandas 本身不支持直接解析任意嵌套 XML;read_xml 只能处理扁平化或简单层级结构,遇到多层嵌套(如 <address><city><name></name></city></address> 套三层)会丢字段或报错。
为什么 read_xml 对嵌套 XML 经常失效
它默认按「同级同名标签」提取列,把 <record></record> 当作行,把其直接子元素(如 <name></name>、<city></city>)当列——但若 <city></city> 实际藏在 <address><location><city></city></location></address> 里,read_xml 就找不到,返回 None 或跳过整条记录。
常见错误现象包括:
-
ValueError: XPath evaluation returned no results(xpath指向了空路径) - 生成的 DataFrame 列数远少于预期,关键字段全为
NaN - 属性(如
id="1")和文本内容混在一起,无法分离
用 xml.etree.ElementTree 手动遍历是最稳的方案
绕过 read_xml 的限制,自己控制节点访问深度。核心是:先定位到最细粒度的“数据单元”(比如每个 <record></record>),再逐个取它的子树中任意层级的值。
实操建议:
- 用
root.findall('.//record')定位所有顶层记录节点(.//支持跨层查找) - 对每个
record,用find('.//city')而不是find('address/city'),避免因中间层缺失(如有的 record 没<address></address>)导致整个字段崩溃 - 取属性用
record.get('id'),取文本用elem.text.strip() if elem is not None else None - 把每条记录构造成字典后
append到列表,最后一次性传给pd.DataFrame(records)
示例片段:
import xml.etree.ElementTree as ET
import pandas as pd
tree = ET.parse('data.xml')
root = tree.getroot()
records = []
for record in root.findall('.//record'):
records.append({
'id': record.get('id'),
'name': (record.find('.//name') or {}).text.strip() if record.find('.//name') is not None else None,
'city': (record.find('.//city') or {}).text.strip() if record.find('.//city') is not None else None,
'zip': (record.find('.//zip') or {}).text.strip() if record.find('.//zip') is not None else None,
})
df = pd.DataFrame(records)
遇到超大 XML 文件时别用 ET.parse()
内存会爆。改用 ET.iterparse() 流式读取,边解析边构建记录,处理完立即丢弃已用节点。
关键点:
- 只监听
'start'和'end'事件,用栈管理当前路径 - 当遇到
record的'start'时清空临时字典;遇到'end'且 tag 是record时,把字典append进结果列表 - 用
elem.clear()和del elem主动释放内存
这步容易被忽略:不主动清理,iterparse 和 parse 内存占用几乎一样。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











