多XML文件解析转CSV问题求助(附Python代码)
问题排查与解决方案
我看了你的代码,核心问题出在CSV文件的打开模式上,这也是处理多文件时数据丢失的主要原因。咱们一步步拆解:
问题1:每次循环覆盖CSV文件
你现在在处理每个XML文件时,都用open('prova.csv','w')打开文件:
csvfile=open('prova.csv','w')
'w'模式是写入模式,每次打开都会清空文件里原有的内容。所以处理第一个XML时会写入数据,但处理第二个XML时,文件被重新清空,之前的数据就没了,最后只会保留最后一个XML的数据(如果最后一个XML能正常提取数据的话)。
问题2:文件操作的最佳实践缺失
直接用open()然后手动close()容易出现遗漏关闭的情况,推荐用with语句自动管理文件上下文,避免资源泄漏。
修改后的代码
我调整了你的代码,解决了上述问题,同时优化了逻辑:
import csv import xml.etree.ElementTree as ET import os path = r"C:\\Users\ADMIN\Desktop\prog" # 用with语句打开CSV文件,只打开一次,用'w'模式写入所有行 with open('prova.csv', 'w', newline='') as csvfile: csv_writer = csv.writer(csvfile) for filename in os.listdir(path): if not filename.endswith('.xml'): continue fullname = os.path.join(path, filename) print(fullname) # 每次处理新的XML,清空数据列表 primo_for = [] try: tree = ET.parse(fullname) root = tree.getroot() print("Dati Riepilogo per aliquota IVA e natura") # 提取DatiRiepilogo数据 for datir in root.iter('DatiRiepilogo'): for element in datir: print(element.tag, element.text) primo_for.append(element.text) # 提取CedentePrestatore数据 for cedente_prestatore in root.iter('CedentePrestatore'): for figlio in cedente_prestatore: for nipote in figlio: for pronipote in nipote: print(pronipote.tag, pronipote.text) primo_for.append(pronipote.text) # 提取DatiGeneraliDocumento数据(排除Divisa) for dati_generali in root.iter('DatiGeneraliDocumento'): for figlio in dati_generali: if figlio.tag != 'Divisa': print(figlio.tag, figlio.text) primo_for.append(figlio.text) # 提取DatiPagamento中的ModalitaPagamento for dati_pagamento in root.iter('DatiPagamento'): for figlio in dati_pagamento: for nipote in figlio: if nipote.tag == 'ModalitaPagamento': print(nipote.tag, nipote.text) primo_for.append(nipote.text) # 写入当前XML的数据行 if primo_for: # 避免写入空行 csv_writer.writerow(primo_for) except Exception as e: print(f"处理文件 {fullname} 时出错: {str(e)}")
关键修改点说明
- CSV文件只打开一次:把
with open(...)放在循环外面,用'w'模式初始化文件,之后每次循环只写入一行数据,不会覆盖之前的内容。 - 用
with语句管理文件:自动帮你关闭文件,不用手动调用csvfile.close()。 - 添加异常捕获:如果某个XML文件格式有问题,不会导致整个脚本崩溃,还能提示错误信息。
- 变量名规范:把
PrimoFor改成小写的primo_for,符合Python的PEP8命名规范,可读性更好。 - 避免空行写入:判断
primo_for不为空时才写入,防止没有提取到数据的XML写入空行。
关于你尝试的os.walk
os.walk()是用来遍历目录及其子目录的,如果你的XML文件分散在子文件夹里,这个方法更合适,但它不是你当前问题的原因。如果需要处理子目录的XML,可以把循环改成这样:
for root_dir, dirs, files in os.walk(path): for filename in files: if not filename.endswith('.xml'): continue fullname = os.path.join(root_dir, filename) # 后续处理逻辑和上面一样
这样就能处理所有子目录里的XML文件了。
内容的提问来源于stack exchange,提问作者Dumitru Cirlan
相关产品推荐
相关产品推荐

