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

Python解析带命名空间的UBL Invoice XML文档问题

解析UBL格式Invoice XML的正确方法

UBL格式XML的核心难点是命名空间的正确映射与使用,xml.etree.ElementTree需要显式指定命名空间才能定位到目标节点。以下是针对你需求的完整解决方案:

1. 定义UBL命名空间映射

UBL发票常用的命名空间需要提前映射,方便后续节点查找:

ns = {
    'cbc': 'urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2',
    'cac': 'urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2',
    'default': 'urn:oasis:names:specification:ubl:schema:xsd:Invoice-2'
}

2. 示例UBL InvoiceLine片段

<Invoice xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2"
         xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2"
         xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2">
    <cac:InvoiceLine>
        <cbc:ID>LINE-001</cbc:ID>
        <cbc:InvoicedQuantity unitCode="PCE">2</cbc:InvoicedQuantity>
        <cbc:LineExtensionAmount currencyID="EUR">200.00</cbc:LineExtensionAmount>
        <cac:Item>
            <cbc:Name>Wireless Mouse</cbc:Name>
            <cbc:Description>Ergonomic wireless optical mouse</cbc:Description>
        </cac:Item>
        <cac:TaxTotal>
            <cbc:TaxAmount currencyID="EUR">42.00</cbc:TaxAmount>
            <cac:TaxSubtotal>
                <cbc:Percent>21</cbc:Percent>
            </cac:TaxSubtotal>
        </cac:TaxTotal>
    </cac:InvoiceLine>
</Invoice>

3. 修正后的解析代码

import xml.etree.ElementTree as ET

# 加载XML文档
tree = ET.parse('your_invoice.xml')  # 替换为你的XML文件路径
root = tree.getroot()

# 提取所有InvoiceLine节点
invoice_lines = root.findall('.//cac:InvoiceLine', ns)

# 遍历提取目标字段
for line in invoice_lines:
    # 基础字段提取
    line_id = line.find('cbc:ID', ns).text
    invoiced_qty = line.find('cbc:InvoicedQuantity', ns).text
    qty_unit = line.find('cbc:InvoicedQuantity', ns).attrib.get('unitCode')
    line_ext_amount = line.find('cbc:LineExtensionAmount', ns).text
    amount_currency = line.find('cbc:LineExtensionAmount', ns).attrib.get('currencyID')
    
    # 商品信息提取
    item = line.find('cac:Item', ns)
    item_name = item.find('cbc:Name', ns).text
    item_desc = item.find('cbc:Description', ns).text
    
    # 税费信息提取
    tax_total = line.find('cac:TaxTotal', ns)
    tax_amount = tax_total.find('cbc:TaxAmount', ns).text
    tax_percent = tax_total.find('.//cbc:Percent', ns).text
    
    # 输出结果(可改为存入字典/列表)
    print(f"行ID: {line_id}")
    print(f"开票数量: {invoiced_qty} {qty_unit}")
    print(f"行扩展金额: {line_ext_amount} {amount_currency}")
    print(f"商品名称: {item_name}")
    print(f"商品描述: {item_desc}")
    print(f"税额: {tax_amount} {amount_currency}")
    print(f"税率: {tax_percent}%")
    print("-" * 30)

4. 关键注意事项

  • 所有节点查找必须传入命名空间映射参数ns,否则无法识别带前缀的UBL节点。
  • 带属性的节点(如InvoicedQuantity的unitCode),通过.attrib.get()提取属性值。
  • 层级较深的节点(如Percent),可使用相对路径'.//cbc:Percent'直接定位,无需逐层查找。
  • 若你的XML命名空间前缀不同(比如用ns1代替cbc),只需修改ns字典中的前缀对应关系即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 01:37:18