Python实现XML匹配Excel数据替换标签报错求助
问题
我有多个命名格式为LLL_XXXXXXXXX_title.xml的XML文件(LLL_后固定为8位字符),另有一个含900+行的Excel文件,结构如下:
| reference | dtp1 | dtp2 | dtp3 |
|---|---|---|---|
| ABC0D012 | 1_blabla | 1_1_blablabla | 1_1_1_blablablabla |
| ABC0D013 | 1_blabla | 1_1_blablabla | 1_1_1_blablablabla |
| ABC0D014 | 1_blabla | 1_1_blablabla | 1_1_1_blablablabla |
| ABT0G012 | 1_blabla | 1_1_blablabla | 1_1_1_blablablabla |
XML文件中包含<dtp1>text</dtp1>、<dtp2>text</dtp2>、<dtp3>text</dtp3>标签,我希望通过Python脚本实现:遍历XML文件,提取文件名中LLL_后的8位字符,匹配Excel的reference列,获取对应dtp1、dtp2、dtp3列的值,替换XML标签文本。
我作为Python初学者编写了如下脚本:
import numpy as np import openpyxl import pandas as pd import xml.etree.ElementTree as ET import os table1 = pd.read_excel('C:/Users/Documents/datatypes.xlsx', na_values=['NA']) table2 = table1.replace('\xa0', ' ',regex=True) for root, dirs, files in os.walk("."): for file in files : if file[-4:] == '.xml': #print(file) xml = ET.parse('LLL_ABC0D012_title.xml') root = xml.getroot() dtp1_xml = root[8] dtp2_xml = root[9] dtp3_xml = root[10] num = file[4:12] #print(num) dtp1_excel = table2['dtp1'].where(table2['reference'] == num) dtp1_xml.text = dtp1_excel #print(dtp1_xml.text) ET.indent(root) xml.write("LLL_ABC0D012_title.xml", encoding='utf-8', xml_declaration=True, method='xml')
但脚本运行异常,dtp1_excel未返回匹配的单元格值,而是输出全NaN的Series:
0 NaN 1 NaN 2 NaN 3 NaN 4 NaN ... 931 NaN 932 NaN 933 NaN 934 NaN 935 NaN Name: dtp1, Length: 936, dtype: object
我的Excel中reference和dtp1列无NaN值,应该只返回单个单元格值。请问我的实现思路哪里出错了?
问题分析与修复方案
核心错误点
- 硬编码XML文件名:脚本固定解析
LLL_ABC0D012_title.xml,未处理循环到的当前XML文件,导致提取的num与实际操作文件不匹配。 where方法使用错误:table2['dtp1'].where(...)会返回完整Series,仅保留匹配位置的值,其余设为NaN,无法直接获取单个匹配值。- 固定索引访问XML元素风险高:用
root[8]、root[9]这种索引定位标签,XML结构变化就会失效,应按标签名查找。 - 硬编码输出文件名:写入时固定用
LLL_ABC0D012_title.xml,会覆盖原文件且无法处理其他XML。
修复后的脚本
import pandas as pd import xml.etree.ElementTree as ET import os # 读取Excel并构建快速匹配的字典映射 table = pd.read_excel('C:/Users/Documents/datatypes.xlsx', na_values=['NA']) table = table.replace('\xa0', ' ', regex=True) # 将reference设为索引,转成字典,后续通过键直接取值,效率更高 ref_map = table.set_index('reference')[['dtp1', 'dtp2', 'dtp3']].to_dict('index') # 遍历所有XML文件 for root_dir, _, files in os.walk("."): for file in files: if file.endswith('.xml'): # 提取文件名中LLL_后的8位字符 if len(file) >= 12 and file.startswith('LLL_'): num = file[4:12] # 检查是否存在匹配的reference if num in ref_map: dtp_values = ref_map[num] # 解析当前XML文件(拼接完整路径) xml_path = os.path.join(root_dir, file) tree = ET.parse(xml_path) xml_root = tree.getroot() # 按标签名查找并替换文本 dtp1_elem = xml_root.find('dtp1') if dtp1_elem is not None: dtp1_elem.text = dtp_values['dtp1'] dtp2_elem = xml_root.find('dtp2') if dtp2_elem is not None: dtp2_elem.text = dtp_values['dtp2'] dtp3_elem = xml_root.find('dtp3') if dtp3_elem is not None: dtp3_elem.text = dtp_values['dtp3'] # 保存修改后的XML(覆盖原文件,如需保留原文件可修改文件名) ET.indent(xml_root) tree.write(xml_path, encoding='utf-8', xml_declaration=True, method='xml') else: print(f"未找到匹配的reference:{num},文件:{file}") else: print(f"文件名格式不符合要求:{file}")
关键优化说明
- 将Excel的
reference设为索引并转成字典,匹配时直接通过键取值,比循环查找效率高,适合900+行的数据集。 - 用
file.endswith('.xml')替代file[-4:] == '.xml',更简洁可靠。 - 用
os.path.join拼接完整文件路径,避免子目录下的文件路径错误。 - 添加格式检查和存在性判断,避免因文件名错误或无匹配数据导致崩溃,同时输出提示便于排查。
- 用
find()按标签名查找元素,避免XML结构变化导致的索引错误。
内容的提问来源于stack exchange,提问作者Camille
相关产品推荐
相关产品推荐

