场景
将批量的XML发票信息提取汇总到EXCEL中
解析XML发票
python
import xml.etree.ElementTree as ET
tree = ET.parse("./【365约车特选-39.54元-1个行程】高德打车电子发票.xml")
root = tree.getroot()
for child in root:
print("一级分支",child.tag, child.attrib)
for subchild in child:
print("--二级分支",subchild.tag, subchild.attrib,subchild.text)
for subsubchild in subchild:
print("----三级分支", subsubchild.tag,subsubchild.attrib,subsubchild.text)
一级分支 Header {}
--二级分支 EIid {} 26327000001329568432
--二级分支 EInvoiceTag {} SWEI3200
--二级分支 Version {} 0.32
--二级分支 InherentLabel {} None
----三级分支 InIssuType {} None
----三级分支 EInvoiceType {} None
----三级分支 GeneralOrSpecialVAT {} None
----三级分支 TaxpayerType {} None
--二级分支 UndefinedLabel {} None
----三级分支 Label {} None
----三级分支 Label {} None
----三级分支 Label {} None
一级分支 EInvoiceData {}
--二级分支 SellerInformation {} None
----三级分支 SellerIdNum {} 91320981MAEBB5QA34
----三级分支 SellerName {} 昆明盛智易联科技有限公司东台分公司
----三级分支 SellerAddr {} 东台沿海经济区科创大厦415
----三级分支 SellerTelNum {} 18108755741
----三级分支 SellerBankName {} 中信银行北京北辰支行
----三级分支 SellerBankAccNum {} 8110701013603001914
--二级分支 BuyerInformation {} None
----三级分支 BuyerIdNum {} 91xxxxxxxxxxxxxxxx3
----三级分支 BuyerName {} xxxxxx有限责任公司
----三级分支 BuyerAddr {} None
----三级分支 BuyerTelNum {} None
----三级分支 BuyerBankName {} None
----三级分支 BuyerBankAccNum {} None
--二级分支 BasicInformation {} None
----三级分支 TotalAmWithoutTax {} 38.39
----三级分支 TotalTaxAm {} 1.15
----三级分支 TotalTax-includedAmountInChinese {} 叁拾玖元伍角肆分
----三级分支 TotalTax-includedAmount {} 39.54
----三级分支 RequestTime {} 2026-07-18 23:45:14
----三级分支 Drawer {} 杨艳彩
--二级分支 IssuItemInformation {} None
----三级分支 ItemName {} *交通运输服务*客运服务费
----三级分支 MeaUnits {} None
----三级分支 Quantity {} 1
----三级分支 UnPrice {} 39.35
----三级分支 Amount {} 39.35
----三级分支 TaxRate {} 0.030000
----三级分支 ComTaxAm {} 1.18
----三级分支 TotaltaxIncludedAmount {} 40.53
----三级分支 TaxClassificationCode {} 3010101020203000000
--二级分支 IssuItemInformation {} None
----三级分支 ItemName {} *交通运输服务*客运服务费
----三级分支 Amount {} -0.96
----三级分支 TaxRate {} 0.030000
----三级分支 ComTaxAm {} -0.03
----三级分支 TotaltaxIncludedAmount {} -0.99
----三级分支 TaxClassificationCode {} 3010101020203000000
--二级分支 SpecificInformation {} None
--二级分支 AdditionalInformation {} None
----三级分支 Remark {} None
一级分支 TaxSupervisionInfo {}
--二级分支 InvoiceNumber {} 26327000001329568432
--二级分支 IssueTime {} 2026-07-18
--二级分支 TaxBureauCode {} 13200000000
--二级分支 TaxBureauName {} 国家税务总局江苏省税务局
一级分支 ptbh {}
寻找标签数据
root.findall()
仅查找标记为当前元素直接子级的元素
python
root.findall(".//ItemName")
[<Element 'ItemName' at 0x10c60aac0>, <Element 'ItemName' at 0x10c60aa20>]
python
root.findall(".//ItemName")[0].text
'*交通运输服务*客运服务费'
python
root.findall(".//ItemName")[1].text
'*交通运输服务*客运服务费'
python
root.findall(".//IssuItemInformation/ItemName")[0].text
'*交通运输服务*客运服务费'
root.find()
找到 第一 带有特定标签的子项
python
root.find(".//TotalTax-includedAmount").text
'39.54'
完整脚本代码
python
import xml.etree.ElementTree as ET
from openpyxl import Workbook
from tqdm import tqdm # 进度条工具
import os
from datetime import datetime
wb = Workbook()
ws = wb.active
now = datetime.now()
now = now.strftime("%Y-%m-%d %H-%M-%S")
print("当前日期和时间:", now)
# 获取当前工作目录的完整路径
current_directory_path = os.getcwd()
# 获取当前工作目录的名称
current_directory_name = os.path.basename(current_directory_path)
print("当前工作目录的完整路径:", current_directory_path)
print("当前工作目录的名称:", current_directory_name)
filenames = os.listdir('.')
path_files = []
for filename in filenames:
filename = filename.split('.')
if filename[-1] == 'xml':
filename = str.join('.',filename)
path_file = "./" + filename
path_files.append(path_file)
print(f"文件夹下总共{len(path_files)} 个XML发票文件")
china_name = ["文件名","文件类型","发票号码","开票时间","税务局代码","税务局名称","票据编号","购买方名称","购买方税号","销售方名称","销售方税号","销售方电话","销售方开户银行","销售方开会银行账号","项目名称","规格型号","单位","数量","单价","金额","税率/征收率","税额","价税合计(小写)","价税合计(大写)"]
for i in range(len(china_name)):
ws.cell(row=1,column=i+1).value = china_name[i]
def parse_xml_invoice(xml_path):
tree = ET.parse(xml_path)
root = tree.getroot()
# 提取关键字段
try:
InvoiceNumber = root.find(".//InvoiceNumber").text
except Exception as e:
InvoiceNumber = "未提取成功"
print(f"文件{xml_path}遇到 InvoiceNumber 参数报错{e}")
try:
IssueTime = root.find(".//IssueTime").text
except Exception as e:
IssueTime = "未提取成功"
print(f"文件{xml_path}遇到 IssueTime 参数报错{e}")
try:
TaxBureauCode = root.find(".//TaxBureauCode").text
except Exception as e:
TaxBureauCode = "未提取成功"
print(f"文件{xml_path}遇到 TaxBureauCode 参数报错{e}")
try:
TaxBureauName = root.find(".//TaxBureauName").text
except Exception as e:
TaxBureauName = "未提取成功"
print(f"文件{xml_path}遇到 TaxBureauName 参数报错{e}")
try:
ptbh = root.find(".//ptbh").text
except Exception as e:
ptbh = "未提取成功"
print(f"文件{xml_path}遇到 ptbh 参数报错{e}")
try:
BuyerName = root.find(".//BuyerName").text
except Exception as e:
BuyerName = "未提取成功"
print(f"文件{xml_path}遇到 BuyerName 参数报错{e}")
try:
BuyerIdNum = root.find(".//BuyerIdNum").text
except Exception as e:
BuyerIdNum = "未提取成功"
print(f"文件{xml_path}遇到 BuyerIdNum 参数报错{e}")
try:
SellerName = root.find(".//SellerName").text
except Exception as e:
SellerName = "未提取成功"
print(f"文件{xml_path}遇到 SellerName 参数报错{e}")
try:
SellerIdNum = root.find(".//SellerIdNum").text
except Exception as e:
SellerIdNum = "未提取成功"
print(f"文件{xml_path}遇到 SellerIdNum 参数报错{e}")
try:
SellerTelNum = root.find(".//SellerTelNum").text
except Exception as e:
SellerTelNum = "未提取成功"
print(f"文件{xml_path}遇到 SellerTelNum 参数报错{e}")
try:
SellerBankName = root.find(".//SellerBankName").text
except Exception as e:
SellerBankName = "未提取成功"
print(f"文件{xml_path}遇到 SellerBankName 参数报错{e}")
try:
SellerBankAccNum = root.find(".//SellerBankAccNum").text
except Exception as e:
SellerBankAccNum = "未提取成功"
print(f"文件{xml_path}遇到 SellerBankAccNum 参数报错{e}")
## 判断项目名目有几行
try:
IssuItemInformation_list = root.findall(".//IssuItemInformation")
if len(IssuItemInformation_list) >= 2:
ItemName = "多个项目目录,未提取"
SpecMod = "多个项目目录,未提取"
MeaUnits = "多个项目目录,未提取"
Quantity = "多个项目目录,未提取"
UnPrice = "多个项目目录,未提取"
Amount = "多个项目目录,未提取"
TaxRate = "多个项目目录,未提取"
ComTaxAm = "多个项目目录,未提取"
else:
try:
ItemName = root.find(".//ItemName").text
except Exception as e:
ItemName = "未提取成功"
print(f"文件{xml_path}遇到 ItemName 参数报错{e}")
try:
SpecMod = root.find(".//SpecMod").text
except Exception as e:
SpecMod = "未提取成功"
print(f"文件{xml_path}遇到 SpecMod 参数报错{e}")
try:
MeaUnits = root.find(".//MeaUnits").text
except Exception as e:
MeaUnits = "未提取成功"
print(f"文件{xml_path}遇到 MeaUnits 参数报错{e}")
try:
Quantity = root.find(".//Quantity").text
except Exception as e:
Quantity = "未提取成功"
print(f"文件{xml_path}遇到 Quantity 参数报错{e}")
try:
UnPrice = root.find(".//UnPrice").text
except Exception as e:
UnPrice = "未提取成功"
print(f"文件{xml_path}遇到 UnPrice 参数报错{e}")
try:
Amount = root.find(".//Amount").text
except Exception as e:
Amount = "未提取成功"
print(f"文件{xml_path}遇到 Amount 参数报错{e}")
try:
TaxRate = root.find(".//TaxRate").text
except Exception as e:
TaxRate = "未提取成功"
print(f"文件{xml_path}遇到 TaxRate 参数报错{e}")
try:
ComTaxAm = root.find(".//ComTaxAm").text
except Exception as e:
ComTaxAm = "未提取成功"
print(f"文件{xml_path}遇到 ComTaxAm 参数报错{e}")
except Exception as e:
print(f"文件{xml_path}遇到 IssuItemInformation 分支 参数报错{e}")
try:
TotalTax_includedAmount = root.find(".//TotalTax-includedAmount").text
except Exception as e:
TotalTax_includedAmount = "未提取成功"
print(f"文件{xml_path}遇到 TotalTax_includedAmount 参数报错{e}")
try:
TotalTax_includedAmountInChinese = root.find(".//TotalTax-includedAmountInChinese").text
except Exception as e:
TotalTax_includedAmountInChinese = "未提取成功"
print(f"文件{xml_path}遇到 TotalTax_includedAmountInChinese 参数报错{e}")
context = {}
context = {
"文件名":xml_path,
"文件类型":"XML",
"发票号码":InvoiceNumber,
"开票时间":IssueTime,
"税务局代码":TaxBureauCode,
"税务局名称":TaxBureauName,
"票据编号":ptbh,
"购买方名称":BuyerName,
"购买方税号":BuyerIdNum,
"销售方名称":SellerName,
"销售方税号":SellerIdNum,
"销售方电话":SellerTelNum,
"销售方开户银行":SellerBankName,
"销售方开会银行账号":SellerBankAccNum,
"项目名称":ItemName,
"规格型号":SpecMod,
"单位":MeaUnits,
"数量":Quantity,
"单价":UnPrice,
"金额":Amount,
"税率/征收率":TaxRate,
"税额":ComTaxAm,
"价税合计(小写)":TotalTax_includedAmount,
"价税合计(大写)":TotalTax_includedAmountInChinese
}
return context
i=2
for path_file in path_files:
xml_path = path_file
contexts = parse_xml_invoice(xml_path)
ws.cell(row=i,column=1).value = contexts["文件名"]
ws.cell(row=i,column=2).value = contexts["文件类型"]
ws.cell(row=i,column=3).value = contexts["发票号码"]
ws.cell(row=i,column=4).value = contexts["开票时间"]
ws.cell(row=i,column=5).value = contexts["税务局代码"]
ws.cell(row=i,column=6).value = contexts["税务局名称"]
ws.cell(row=i,column=7).value = contexts["票据编号"]
ws.cell(row=i,column=8).value = contexts["购买方名称"]
ws.cell(row=i,column=9).value = contexts["购买方税号"]
ws.cell(row=i,column=10).value = contexts["销售方名称"]
ws.cell(row=i,column=11).value = contexts["销售方税号"]
ws.cell(row=i,column=12).value = contexts["销售方电话"]
ws.cell(row=i,column=13).value = contexts["销售方开户银行"]
ws.cell(row=i,column=14).value = contexts["销售方开会银行账号"]
ws.cell(row=i,column=15).value = contexts["项目名称"]
ws.cell(row=i,column=16).value = contexts["规格型号"]
ws.cell(row=i,column=17).value = contexts["单位"]
ws.cell(row=i,column=18).value = contexts["数量"]
ws.cell(row=i,column=19).value = contexts["单价"]
ws.cell(row=i,column=20).value = contexts["金额"]
ws.cell(row=i,column=21).value = contexts["税率/征收率"]
ws.cell(row=i,column=22).value = contexts["税额"]
ws.cell(row=i,column=23).value = contexts["价税合计(小写)"]
ws.cell(row=i,column=24).value = contexts["价税合计(大写)"]
i = i+1
wb.save(f'./{current_directory_name}_发票汇总_{str(now)}.xlsx')
print("Finish")