如何在Python中用Schematron和XSD验证CII D16B电子发票XML?
解决Python中EN16931 CII D16B电子发票的Schematron验证问题
针对多命名空间、复杂嵌套规则的EN16931 CII D16B电子发票Schematron验证,推荐以下两种可行的Python实现方案:
方案一:使用lxml结合Schematron转XSLT(免费开源)
Schematron可转换为XSLT执行验证,lxml对XSLT 1.0支持完善,能处理多命名空间场景,步骤如下:
准备依赖文件
- 获取EN16931核心Schematron文件(EN16931-CII-validation.sch)
- 获取标准Schematron转XSLT骨架文件(iso_schematron_skeleton.xsl,可从Schematron官方资源获取)
代码实现
from lxml import etree def validate_cii_invoice(schematron_path, xslt_skeleton_path, invoice_xml_path): # 加载Schematron和转换骨架 schematron_doc = etree.parse(schematron_path) xslt_skeleton = etree.XSLT(etree.parse(xslt_skeleton_path)) # 将Schematron转换为验证用XSLT validation_xslt = xslt_skeleton(schematron_doc) # 加载待验证的发票XML invoice_doc = etree.parse(invoice_xml_path) # 执行验证 validation_result = etree.XSLT(validation_xslt)(invoice_doc) # 解析验证结果 errors = [] ns = {"svrl": "http://purl.oclc.org/dsdl/svrl"} for error in validation_result.xpath("//svrl:failed-assert", namespaces=ns): error_msg = error.xpath("./svrl:text/text()", namespaces=ns)[0] context = error.xpath("./@location", namespaces=ns)[0] errors.append(f"验证失败 [{context}]: {error_msg}") if errors: print("验证不通过:") for err in errors: print(f"- {err}") return False else: print("验证通过") return True # 调用示例 validate_cii_invoice( schematron_path="./EN16931-CII-validation.sch", xslt_skeleton_path="./iso_schematron_skeleton.xsl", invoice_xml_path="./generated_invoice.xml" )
- 关键注意事项
- 确保所有依赖文件路径正确且文件完整
- 转换后的XSLT会继承原Schematron中的命名空间定义,无需手动绑定
- 若出现命名空间相关错误,检查原Schematron是否完整包含CII的四个命名空间声明
方案二:使用SaxonC(商业级支持,需授权)
如果对验证性能和复杂规则兼容性要求更高,可选择SaxonC的Python绑定。它原生支持Schematron 1.5,无需手动转换XSLT,对嵌套规则和多命名空间处理更高效。
安装依赖
获取授权版本后,安装Python绑定:pip install saxonc代码实现
import saxonc def validate_with_saxonc(schematron_path, invoice_xml_path): with saxonc.PySaxonProcessor(license=False) as proc: # 创建Schematron验证器 schema_validator = proc.new_schema_validator() schema_validator.set_schematron_source(XdmNode=proc.parse_xml(xml_file_name=schematron_path)) # 加载待验证XML invoice_node = proc.parse_xml(xml_file_name=invoice_xml_path) # 执行验证 validation_report = schema_validator.validate(node=invoice_node) # 解析结果 if validation_report.is_valid(): print("验证通过") return True else: print("验证不通过:") for error in validation_report.get_error_list(): print(f"- 行{error.line_number}: {error.message}") return False # 调用示例 validate_with_saxonc( schematron_path="./EN16931-CII-validation.sch", invoice_xml_path="./generated_invoice.xml" )
- 关键注意事项
- SaxonC免费版本功能有限,完整支持EN16931规则需商业授权
- 授权版本提供更详细的错误上下文,便于定位问题
内容的提问来源于stack exchange,提问作者Mayot
相关产品推荐
相关产品推荐

