如何用Python累加嵌套XML子元素整数并导出适配QuickBooks的数据?
问题描述
我收到一份包含大量子元素的XML文档,需要提取信息并导出为CSV或文本文件以便导入QuickBooks。XML结构如下:
<MODocuments> <MODocument> <Document>TX1126348</Document> <DocStatus>P</DocStatus> <DateIssued>20180510</DateIssued> <ApplicantName>COMPANY FRUIT & 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 & 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 & 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个,自然都是单个批次的值,不是总和。
修正后的逻辑优势:
- 按文档维度处理:每个文档的所有数据都在同一个循环块里处理,不会出现数据错位
- 清晰的累加逻辑:对每个文档单独初始化总磅数,逐个批次累加,结果准确
- 更简洁的节点查找:用
findall('.//MOLot')直接定位当前文档下的所有批次节点,不用多层嵌套循环 - 易扩展:如果之后要加更多字段,直接在元组里添加就行,导出CSV也很方便
运行这个代码,就能得到你想要的输出结果啦!
内容的提问来源于stack exchange,提问作者Simon
相关产品推荐
相关产品推荐

