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

如何用Python累加嵌套XML子元素整数并导出适配QuickBooks的数据?

问题描述

我收到一份包含大量子元素的XML文档,需要提取信息并导出为CSV或文本文件以便导入QuickBooks。XML结构如下:

<MODocuments> 
  <MODocument> 
    <Document>TX1126348</Document> 
    <DocStatus>P</DocStatus> 
    <DateIssued>20180510</DateIssued> 
    <ApplicantName>COMPANY FRUIT &amp; VEGETABLE</ApplicantName> 
    <MOLots> 
      <MOLot> 
        <LotID>A</LotID> 
        <ProductVariety>Yellow</ProductVariety> 
        <TotalPounds>15500</TotalPounds> 
      </MOLot> 
      <MOLot> 
        <LotID>B</LotID> 
        <ProductVariety>Yellow</ProductVariety> 
        <TotalPounds>175</TotalPounds> 
      </MOLot> 
      <MOLot> 
        <LotID>C</LotID> 
        <ProductVariety>Yellow</ProductVariety> 
        <TotalPounds>7500</TotalPounds> 
      </MOLot> 
      <MOLot> 
        <LotID>D</LotID> 
        <ProductVariety>Yellow</ProductVariety> 
        <TotalPounds>300</TotalPounds> 
      </MOLot> 
    </MOLots> 
  </MODocument> 
  <MODocument> 
    <Document>TX1126349</Document> 
    <DocStatus>P</DocStatus> 
    <DateIssued>20180511</DateIssued> 
    <ApplicantName>COMPANY FRUIT &amp; VEGETABLE</ApplicantName> 
    <MOLots> 
      <MOLot> 
        <LotID>A</LotID> 
        <ProductVariety>Yellow</ProductVariety> 
        <TotalPounds>25200</TotalPounds> 
      </MOLot> 
      <MOLot> 
        <LotID>B</LotID> 
        <ProductVariety>Yellow</ProductVariety> 
        <TotalPounds>16800</TotalPounds> 
      </MOLot> 
    </MOLots> 
  </MODocument> 
  <MODocument> 
    <Document>TX1126350</Document> 
    <DateIssued>20180511</DateIssued> 
    <ApplicantName>COMPANY FRUIT &amp; VEGETABLE</ApplicantName> 
    <MOLots> 
      <MOLot> 
        <LotID>A</LotID> 
        <ProductVariety>Yellow</ProductVariety> 
        <TotalPounds>14100</TotalPounds> 
      </MOLot> 
    </MOLots> 
  </MODocument> 
</MODocuments> 

需求

提取每个MODocument父元素下的:

  • Document编号
  • ApplicantName
  • 该文档下所有MOLot的TotalPounds累加值

期望输出:

TX1126348 COMPANY FRUIT & VEGETABLE 23475 
TX1126349 COMPANY FRUIT & VEGETABLE 42000 
TX1126350 COMPANY FRUIT & VEGETABLE 14100 

现有代码

import xml.etree.ElementTree as ET 
tree = ET.parse('TX_959_20180514131311.xml') 
root = tree.getroot() 
docCert = [] 
docComp = [] 
totalPounds=[] 
for MODocuments in root: 
    for MODocument in MODocuments: 
        docCert.append(MODocument.find('Document').text) 
        docComp.append(MODocument.find('ApplicantName').text) 
        for MOLots in MODocument: 
            for MOLot in MOLots: 
                totalPounds.append(int(MOLot.find('TotalPounds').text)) 
for i in range(len(docCert)): 
    print(i, docCert[i],' ', docComp[i], totalPounds[i]) 

错误输出

0 TX1126348 COMPANY FRUIT & VEGETABLE 15500 
1 TX1126349 COMPANY FRUIT & VEGETABLE 175 
2 TX1126350 COMPANY FRUIT & VEGETABLE 7500 

现在我不清楚该如何为每个Document累加总磅数,请求技术帮助。


解决方案

嘿,我看看你的问题——你现在的代码是把每个批次的磅数单独存进totalPounds列表里,但没有为每个文档做汇总,所以才会出现索引不匹配,输出的磅数都是单个批次的值,而不是每个文档的总和。咱们来修正这个逻辑:

首先,问题核心是:每个文档对应多个批次,你需要先把当前文档下所有批次的磅数加起来,再和文档编号、申请人名称对应上,而不是把所有批次的磅数都堆在一个列表里。

下面是修正后的代码,我加了详细的注释:

import xml.etree.ElementTree as ET 

tree = ET.parse('TX_959_20180514131311.xml') 
root = tree.getroot() 

# 用一个列表存每个文档的完整数据,每个元素是(文档编号, 申请人名称, 总磅数)的元组
document_records = []

# 直接遍历root下的所有MODocument节点(root就是MODocuments,子节点就是每个文档)
for doc in root.findall('MODocument'):
    # 提取当前文档的编号和申请人名称
    doc_number = doc.find('Document').text
    applicant_name = doc.find('ApplicantName').text
    
    # 初始化当前文档的总磅数为0
    current_total = 0
    # 找到当前文档下所有的MOLot节点
    all_lots = doc.findall('.//MOLot')
    for lot in all_lots:
        # 把每个批次的磅数转成整数,累加到总磅数里
        pounds = int(lot.find('TotalPounds').text)
        current_total += pounds
    
    # 把当前文档的完整信息加入列表
    document_records.append( (doc_number, applicant_name, current_total) )

# 输出结果,格式和你期望的一致
for record in document_records:
    print(f"{record[0]} {record[1]} {record[2]}")

# 如果要导出成CSV文件,直接用csv模块就行(可选)
# import csv
# with open('quickbooks_import.csv', 'w', newline='', encoding='utf-8') as f:
#     writer = csv.writer(f, delimiter=' ')  # 用空格分隔,或者换成','符合标准CSV格式
#     writer.writerows(document_records)

为什么原来的代码不行?

你原来的逻辑是:

  • 每遍历一个MODocument,就把文档编号和申请人名称各加一个到列表里
  • 然后遍历该文档下的每个MOLot,把每个批次的磅数单独加到totalPounds列表里
  • 最后按索引对应,这就导致totalPounds的长度比docCert和docComp长很多,而你只取了前3个,自然都是单个批次的值,不是总和。

修正后的逻辑优势:

  1. 按文档维度处理:每个文档的所有数据都在同一个循环块里处理,不会出现数据错位
  2. 清晰的累加逻辑:对每个文档单独初始化总磅数,逐个批次累加,结果准确
  3. 更简洁的节点查找:用findall('.//MOLot')直接定位当前文档下的所有批次节点,不用多层嵌套循环
  4. 易扩展:如果之后要加更多字段,直接在元组里添加就行,导出CSV也很方便

运行这个代码,就能得到你想要的输出结果啦!

内容的提问来源于stack exchange,提问作者Simon

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 10:09:42