You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

多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)}")

关键修改点说明

  1. CSV文件只打开一次:把with open(...)放在循环外面,用'w'模式初始化文件,之后每次循环只写入一行数据,不会覆盖之前的内容。
  2. 用with语句管理文件:自动帮你关闭文件,不用手动调用csvfile.close()。
  3. 添加异常捕获:如果某个XML文件格式有问题,不会导致整个脚本崩溃,还能提示错误信息。
  4. 变量名规范:把PrimoFor改成小写的primo_for,符合Python的PEP8命名规范,可读性更好。
  5. 避免空行写入:判断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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 04:38:22