基于ZATCA规范的UBL 2.1 XML验证失败问题求助
ZATCA UBL 2.1 XML验证失败问题排查
问题背景
正在验证符合沙特阿拉伯ZATCA(扎卡特、税务和海关局)规范的UBL 2.1标准XML,使用Python的json2xml包从JSON生成XML,但无法通过ZATCA沙箱验证器的验证,返回XSD_SCHEMA_ERROR错误。
验证器返回错误
category : XSD_SCHEMA_ERROR
code :SAXParseException
message : Schema validation failed; XML does not comply with UBL 2.1 standards in line with ZATCA specifications
生成的XML代码
<?xml version="1.0" ?> <Invoice> <ProfileID>reporting:1.0</ProfileID> <ID>INV004</ID> <UUID>fd5a7cc4-2316-49ee-ac07-6f4be4be3731</UUID> <IssueDate>2022-08-13</IssueDate> <IssueTime>23:46:07</IssueTime> <InvoiceTypeCode>388</InvoiceTypeCode> <InvoiceTypeCodeName>0101001</InvoiceTypeCodeName> <DocumentCurrencyCode>SAR</DocumentCurrencyCode> <TaxCurrencyCode>SAR</TaxCurrencyCode> <Note/> <OrderReference> <ID/> </OrderReference> <ContractDocumentReference> <ID/> </ContractDocumentReference> <AdditionalDocumentReference> <UUID>4</UUID> <PIH> <Attachment> <EmbeddedDocumentBinaryObject>ET05jV7roub7D66wOAQ49TQ8mCkyldhmH7B8CV3Rc6g=</EmbeddedDocumentBinaryObject> </Attachment> </PIH> <QR> <Attachment> <EmbeddedDocumentBinaryObject>5D6ZU7f6nb+s1szmMw46l4NZ7yTy0p1wi0ZUMsdQWBE=</EmbeddedDocumentBinaryObject> </Attachment> </QR> </AdditionalDocumentReference> <Signature> <ID>urn:oasis:names:specification: ubl:signature:Invoice</ID> <SignatureMethod>urn:oasis:names:specification:ubl:dsig:enveloped: xades</SignatureMethod> </Signature> <AccountingSupplierParty> <Party> <PartyLegalEntity> <RegistrationName>Altaf Miazee</RegistrationName> </PartyLegalEntity> <PartyIdentification> <ID/> </PartyIdentification> <PartyTaxScheme> <CompanyID>300600363600003</CompanyID> </PartyTaxScheme> <PostalAddress> <Country> <IdentificationCode>BD</IdentificationCode> </Country> <AdditionalStreetName>Altafbari</AdditionalStreetName> <StreetName>dhaka</StreetName> <BuildingNumber>1233</BuildingNumber> <PlotIdentification>1233</PlotIdentification> <CityName>Dhaka</CityName> <PostalZone>12302</PostalZone> <CountrySubentity>Dhaka</CountrySubentity> <CitySubdivisionName>miazee</CitySubdivisionName> </PostalAddress> </Party> </AccountingSupplierParty> <AccountingCustomerParty> <Party> <PartyLegalEntity> <RegistrationName>Hosen MD Altaf</RegistrationName> </PartyLegalEntity> <PartyIdentification> <ID>398765409876333</ID> </PartyIdentification> <PartyTaxScheme> <CompanyID>398765409876333</CompanyID> </PartyTaxScheme> <PostalAddress> <StreetName>الملك سلمان</StreetName> <AdditionalStreetName>الملك سلمان</AdditionalStreetName> <BuildingNumber>1234</BuildingNumber> <PlotIdentification>1234</PlotIdentification> <CityName>dhaka</CityName> <PostalZone>12234</PostalZone> <CountrySubentity>Dhaka</CountrySubentity> <CitySubdivisionName>الملك سلمان</CitySubdivisionName> <Country> <IdentificationCode>BD</IdentificationCode> </Country> </PostalAddress> </Party> </AccountingCustomerParty> <Delivery> <ActualDeliveryDate>2022-08-25</ActualDeliveryDate> <LatestDeliveryDate/> </Delivery> <PaymentMeans> <PaymentMeansCode>10</PaymentMeansCode> <PayeeFinancialAccount> <PaymentNote/> </PayeeFinancialAccount> </PaymentMeans> <AllowanceCharge> <TaxCategory> <ID>S</ID> <Percent>0.0</Percent> <TaxScheme> <ID>VAT</ID> </TaxScheme> </TaxCategory> <ChargeIndicator>False</ChargeIndicator> <MultiplierFactorNumeric>52.1</MultiplierFactorNumeric> <Amount>0.00</Amount> <AmountcurrencyID>SAR</AmountcurrencyID> <BaseAmount>164263.68</BaseAmount> <BaseAmountcurrencyID>SAR</BaseAmountcurrencyID> </AllowanceCharge> <LegalMonetaryTotal> <LineExtensionAmount>164263.68</LineExtensionAmount> <LineExtensionAmountCurrencyID>SAR</LineExtensionAmountCurrencyID> <AllowanceTotalAmount>0.00</AllowanceTotalAmount> <AllowanceTotalAmountcurrencyID>SAR</AllowanceTotalAmountcurrencyID> <TaxExclusiveAmount>146664.00</TaxExclusiveAmount> <TaxExclusiveAmountcurrencyID>SAR</TaxExclusiveAmountcurrencyID> <TaxInclusiveAmount>164263.68</TaxInclusiveAmount> <TaxInclusiveAmountcurrencyID>SAR</TaxInclusiveAmountcurrencyID> <PrepaidAmount/> <PrepaidAmountcurrencyID>SAR</PrepaidAmountcurrencyID> <PayableAmount>164263.68</PayableAmount> <PayableAmountcurrencyID>SAR</PayableAmountcurrencyID> </LegalMonetaryTotal> <TaxTotal> <TaxAmount>17599.68</TaxAmount> <VatAmountCurrency>SAR</VatAmountCurrency> <VatAmountInAccountingCurrency>17599.68</VatAmountInAccountingCurrency> <CurrencyForVatAmountInAccountingCurrency>SAR</CurrencyForVatAmountInAccountingCurrency> <TaxSubtotal> <TaxableAmount>146664.0</TaxableAmount> <TaxableAmountcurrencyID>SAR</TaxableAmountcurrencyID> <TaxCategory> <ID>E</ID> <Percent>1</Percent> <TaxExemptionReasonCode>TYIEWE</TaxExemptionReasonCode> <TaxExemptionReason>lksdkskak</TaxExemptionReason> <TaxScheme> <ID>10.12</ID> </TaxScheme> </TaxCategory> <TaxAmountcurrencyID>SAR</TaxAmountcurrencyID> </TaxSubtotal> <TaxAmountcurrencyID>SAR</TaxAmountcurrencyID> </TaxTotal> <InvoiceLine> <item> <ID>1</ID> <InvoicedQuantity>12</InvoicedQuantity> <InvoicedQuantityUnitCode>nos</InvoicedQuantityUnitCode> <LineExtensionAmount>146664.0</LineExtensionAmount> <LineExtensionAmountcurrencyID>SAR</LineExtensionAmountcurrencyID> <AllowanceCharge> <ChargeIndicator>False</ChargeIndicator> <MultiplierFactorNumeric>0.0</MultiplierFactorNumeric> <Amount>0</Amount> <AmountcurrencyID>SAR</AmountcurrencyID> <BaseAmount>146664.0</BaseAmount> <BaseAmountcurrencyID>SAR</BaseAmountcurrencyID> </AllowanceCharge> <TaxTotal> <TaxAmount>17599.68</TaxAmount> <TaxAmountcurrencyID>SAR</TaxAmountcurrencyID> <RoundingAmount>164263.68</RoundingAmount> <RoundingAmountcurrencyID>SAR</RoundingAmountcurrencyID> </TaxTotal> <Item> <Name>altaf</Name> <BuyersItemIdentification> <ID/> </BuyersItemIdentification> <SellersItemIdentification> <ID>ITM9</ID> </SellersItemIdentification> <StandardItemIdentification> <ID/> </StandardItemIdentification> <ClassifiedTaxCategory> <ID>2</ID> <Percent>12.00</Percent> <TaxScheme> <ID>VAT</ID> </TaxScheme> </ClassifiedTaxCategory> </Item> <Price> <PriceAmount>12222.00</PriceAmount> <PriceAmountschemeID>SAR</PriceAmountschemeID> <AllowanceCharge> <ChargeIdicator>False</ChargeIdicator> <Amount>0</Amount> <AmountcurrencyID>SAR</AmountcurrencyID> <BaseAmount>164263.68</BaseAmount> <BaseAmountcurrencyID>SAR</BaseAmountcurrencyID> </AllowanceCharge> <BaseQuantity>12</BaseQuantity> <BaseQuantityUnitCode/> </Price> </item> </InvoiceLine> </Invoice>
生成XML的Python代码
def download_invoice_xml(request, invoice_type, invoice_no): in_data = InvoiceReport.objects.filter(invoice_type=invoice_type, invoice_number=invoice_no) for inv in in_data: jsonData = inv.invoice_data mode = inv.creation_mode # Issuetime = jsonData['IssueTime'] # d1 = datetime.strptime(Issuetime, "%Y-%m-%dT%H:%M:%S") # dt_to_string = d1.strftime('%d-%m-%Y %H:%M:%S') # jsonData['IssueTime'] = dt_to_string # # Issuedate = jsonData['IssueDate'] # d2 = datetime.strptime(Issuedate, "%Y-%m-%d") # dt_to_string2 = d1.strftime('%d-%m-%Y') # jsonData['IssueDate'] = dt_to_string2 if jsonData.get('AllowanceCharge').get('ChargeIndicator') == 0: jsonData['AllowanceCharge']['ChargeIndicator'] = False for i in jsonData.get('InvoiceLine'): if i.get('AllowanceCharge').get('ChargeIndicator') == 0: i['AllowanceCharge']['ChargeIndicator'] = False if i.get('Price').get('AllowanceCharge').get('ChargeIndicator') == 0: i['Price']['AllowanceCharge']['ChargeIndicator'] = False xml_output = json2xml.Json2xml(jsonData, wrapper="Invoice", pretty=True, attr_type=False).to_xml() now = datetime.now() if xml_output: response = HttpResponse(xml_output, content_type='application/xml') xml_date = jsonData['IssueDate'].replace("-", "") xml_time = jsonData['IssueTime'].replace(":", "") filename = jsonData['AccountingSupplierParty']['Party']['PartyTaxScheme']['CompanyID'] + "_" + \ xml_date + "T" + xml_time + "_" + str(jsonData['ID']) + ".xml" # filename = jsonData['AccountingSupplierParty']['Party']['PartyIdentification']['ID'] + "_%s_%s.xml" % ( # str((now.strftime("%Y%m%d%H%M%S"))), jsonData['ID']) content = "attachment; filename=%s" % (filename) response['Content-Disposition'] = content return response return HttpResponse("Not found")
问题排查方向
- 根元素命名空间缺失:UBL 2.1标准要求
<Invoice>根元素必须包含命名空间声明(如xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2"),当前XML无命名空间,是验证失败的核心原因之一。 - 自定义元素违规:
<InvoiceTypeCodeName>、<PIH>、<QR>等非UBL 2.1标准元素,不符合ZATCA规范要求,需移除或替换为标准字段。 - 元素拼写错误:
<ChargeIdicator>应为<ChargeIndicator>,拼写错误直接导致验证失败。 - 金额字段结构错误:UBL 2.1中金额字段需通过
currencyID属性指定货币(如<Amount currencyID="SAR">0.00</Amount>),而非单独的<AmountcurrencyID>子元素。 - 空元素不符合约束:
<Note/>、<OrderReference><ID/></OrderReference>等空元素可能违反XSD对必填/可选元素的约束,需确认ZATCA规范是否允许。 - 签名元素不完整:
<Signature>仅包含ID和方法,缺少UBL 2.1要求的完整XAdES签名结构。
修复建议
- 为根元素添加UBL 2.1及ZATCA扩展命名空间。
- 删除所有非标准自定义元素,替换为ZATCA规范定义的字段。
- 修正元素拼写错误,确保名称与UBL 2.1标准一致。
- 调整金额字段结构,使用
currencyID属性指定货币代码。 - 移除不必要的空元素,或按规范填充必填内容。
- 完善数字签名部分,符合UBL 2.1的XAdES签名要求。
内容的提问来源于stack exchange,提问作者Hosen MD Altaf
相关产品推荐
相关产品推荐

