如何用etree.ElementTree将多层XML文件加载到DataFrame?
解决XML转DataFrame空值及结构解析问题
原代码核心问题
- 节点大小写不匹配:XML中的记录节点是
<Record>,但代码中使用root.findall('record')(全小写),导致无法匹配到任何节点,最终生成空DataFrame。 - 字段提取逻辑错误:Record下的
<Field>节点通过name属性区分不同字段,原代码用elem.tag(固定为Field)作为字典键,会导致字段值被重复覆盖,无法正确提取ParaA等字段。 - 未处理Row节点:原代码未遍历Record下的动态Row节点,无法将Record级的公共字段(如ParaA)与每个Row的字段合并,生成目标格式的行数据。
修正后的代码(支持多XML文件)
import pandas as pd import xml.etree.ElementTree as ET from pathlib import Path # 定义要处理的XML文件路径列表 xml_files = [r'.\Test.xml', r'.\Test2.xml'] # 可添加更多文件 target_columns = ['ParaA', 'Para1', 'Para2', 'Para3', 'Para4'] data = [] for file_path in xml_files: if not Path(file_path).exists(): print(f"文件不存在:{file_path}") continue tree = ET.parse(file_path) root = tree.getroot() # 匹配大写的Record节点 for record in root.findall('Record'): # 提取Record级的公共字段(如ParaA) record_common = {} for field in record.findall('Field'): field_name = field.get('name') if field_name in target_columns: record_common[field_name] = field.text # 遍历每个Row节点,合并公共字段与Row字段 for row in record.findall('Row'): row_data = record_common.copy() for field in row.findall('Field'): field_name = field.get('name') if field_name in target_columns: row_data[field_name] = field.text data.append(row_data) # 生成DataFrame并指定列顺序 df = pd.DataFrame(data, columns=target_columns) print(df)
代码说明
- 节点匹配修正:将
root.findall('record')改为root.findall('Record'),匹配XML中的节点大小写。 - 字段提取逻辑:通过
field.get('name')获取Field节点的属性名作为字典键,确保每个字段正确映射。 - Row节点处理:每个Record下的Row节点会复制一份公共字段字典,再添加自身的字段,生成独立的行数据,保证ParaA等公共字段与Row字段一一对应。
- 多文件支持:通过遍历文件列表处理多个XML,同时添加文件存在性检查避免报错。
- 目标列过滤:只提取
target_columns中定义的字段,符合需求的输出格式。
内容的提问来源于stack exchange,提问作者credenco
相关产品推荐
相关产品推荐

