验证XML文件是否符合中国数电票(全面数字化电子发票)格式规范。
数电票XML必须包含以下核心结构和字段:
EInvoice必需子元素:
EIid - 发票唯一标识(20位数字)EInvoiceTag - 发票标签(如 SWEI4400)Version - 版本号InherentLabel - 固有标签(包含发票类型信息)必需包含以下部分:
SellerInformation - 销售方信息(SellerIdNum, SellerName)BuyerInformation - 购买方信息(BuyerIdNum, BuyerName)BasicInformation - 基本信息(金额、开票时间等)IssuItemInformation - 开票项目信息(至少一个)AuthenticationMethods - 认证方式InvoiceNumber - 发票号码(20位)IssueTime - 开票日期TaxBureauCode - 税务局代码TaxBureauName - 税务局名称SignatureValue - 签名值(包含数字签名)EInvoice使用以下Python脚本进行验证:
import xml.etree.ElementTree as ET
import re
def validate_einvoice_xml(file_path):
"""
验证XML是否为数电票格式
返回: (is_valid: bool, message: str, details: dict)
"""
result = {
"is_valid_xml": False,
"has_einvoice_root": False,
"has_required_fields": False,
"invoice_number": None,
"seller_id": None,
"buyer_id": None,
"errors": []
}
try:
# 1. 解析XML
tree = ET.parse(file_path)
root = tree.getroot()
result["is_valid_xml"] = True
# 2. 检查根元素
if root.tag != "EInvoice":
result["errors"].append(f"根元素应为 'EInvoice',实际为 '{root.tag}'")
return False, "非数电票格式:根元素不匹配", result
result["has_einvoice_root"] = True
# 3. 检查必需字段
ns = {'': root.tag} # 处理命名空间
# 检查 EIid
eiid = root.find('.//EIid')
if eiid is None or not eiid.text:
result["errors"].append("缺少必需字段: Header/EIid")
elif eiid.text and not re.match(r'^\d{20}$', eiid.text.strip()):
result["errors"].append(f"EIid 应为20位数字,实际为: {eiid.text}")
# 检查 EInvoiceTag
einvoice_tag = root.find('.//EInvoiceTag')
if einvoice_tag is None or not einvoice_tag.text:
result["errors"].append("缺少必需字段: Header/EInvoiceTag")
# 检查 InvoiceNumber (20位数电票号码)
invoice_num = root.find('.//InvoiceNumber')
if invoice_num is not None and invoice_num.text:
result["invoice_number"] = invoice_num.text.strip()
if not re.match(r'^\d{20}$', invoice_num.text.strip()):
result["errors"].append(f"InvoiceNumber 应为20位数字,实际为: {invoice_num.text}")
# 检查销售方纳税人识别号
seller_id = root.find('.//SellerIdNum')
if seller_id is not None and seller_id.text:
result["seller_id"] = seller_id.text.strip()
# 检查购买方纳税人识别号
buyer_id = root.find('.//BuyerIdNum')
if buyer_id is not None and buyer_id.text:
result["buyer_id"] = buyer_id.text.strip()
# 检查数字签名
signature = root.find('.//SignatureValue')
if signature is None or not signature.text:
result["errors"].append("缺少数字签名: TaxBureauSignature/SignatureValue")
# 检查税务局信息
tax_bureau = root.find('.//TaxBureauName')
if tax_bureau is None or not tax_bureau.text:
result["errors"].append("缺少税务局信息: TaxSupervisionInfo/TaxBureauName")
# 判定结果
if len(result["errors"]) == 0:
result["has_required_fields"] = True
return True, "验证通过:该XML是有效的数电票格式", result
else:
return False, f"验证失败:发现 {len(result['errors'])} 个问题", result
except ET.ParseError as e:
result["errors"].append(f"XML解析错误: {str(e)}")
return False, "XML格式错误:无法解析文件", result
except Exception as e:
result["errors"].append(f"验证过程出错: {str(e)}")
return False, f"验证异常: {str(e)}", result
def print_validation_report(file_path):
"""打印详细的验证报告"""
is_valid, message, details = validate_einvoice_xml(file_path)
print("=" * 60)
print("数电票XML验证报告")
print("=" * 60)
print(f"文件路径: {file_path}")
print(f"验证结果: {'✓ 通过' if is_valid else '✗ 失败'}")
print(f"结果说明: {message}")
print("-" * 60)
if details["invoice_number"]:
print(f"发票号码: {details['invoice_number']}")
if details["seller_id"]:
print(f"销售方税号: {details['seller_id']}")
if details["buyer_id"]:
print(f"购买方税号: {details['buyer_id']}")
if details["errors"]:
print("\n问题列表:")
for i, error in enumerate(details["errors"], 1):
print(f" {i}. {error}")
print("=" * 60)
return is_valid
# 使用示例
if __name__ == "__main__":
import sys
if len(sys.argv) > 1:
print_validation_report(sys.argv[1])
else:
print("用法: python validate_einvoice.py <xml文件路径>")
如果只需要快速判断,检查以下3个关键特征:
EInvoice - 区别于传统发票的 InvoiceTaxBureauSignature - 税务局数字签名满足以上3点,基本可以确定为数电票XML。
| 特征 | 数电票 | 传统电子发票 |
|---|---|---|
| ------ | -------- | ------------- |
| 根元素 | EInvoice | Invoice |
| 发票号码 | 20位数字 | 8位或12位 |
| 发票代码 | 无 | 有(10位或12位) |
| 数字签名 | TaxBureauSignature | 可能不同 |
| 版本标识 | Version字段 | 可能无 |
验证完成后,输出以下格式的报告:
## 数电票验证结果
**文件**: [文件名]
**验证结果**: [通过/失败]
**发票信息**:
- 发票号码: [20位号码]
- 销售方: [纳税人识别号]
- 购买方: [纳税人识别号]
- 开票日期: [日期]
**详细检查**:
- [x] XML格式正确
- [x] 根元素为EInvoice
- [x] 包含EIid字段(20位)
- [x] 包含发票号码(20位)
- [x] 包含数字签名
- [ ] [如有失败项]
**结论**: [该文件是/不是]有效的数电票XML
共 1 个版本