lxml.isoschematron无法编译测试表达式,求可行解决办法
问题描述
我正尝试使用RNG schema,通过lxml结合RelaxNG和Schematron规则验证XML。这种方式在TEI这类复杂XML场景中很常见,但找到低依赖的可靠验证器却出奇困难。我反复遇到lxml.etree.XSLTParseError错误,涉事测试表达式在其他环境中可正常运行,想知道可行的解决办法。
以下是最小复现示例:
from io import StringIO from lxml import etree, isoschematron f = StringIO( """\ <schema xmlns="http://purl.oclc.org/dsdl/schematron" > <pattern id="origDate"> <title>Original date rule</title> <rule context="Total"> <assert test="@calendar and (@when or @notBefore or @notAfter or @from or @to) and string-length(normalize-space(string())) gt 0">A test rule.</assert> </rule> </pattern> </schema> """ ) sct_doc = etree.parse(f) schematron = isoschematron.Schematron(sct_doc)
完整错误信息:lxml.etree.XSLTParseError: xsl:when : could not compile test expression '@calendar and (@when or @notBefore or @notAfter or @from or @to) and string-length(normalize-space(string())) gt 0'
错误原因
lxml的isoschematron模块默认基于XSLT 1.0实现Schematron验证,而表达式中的gt是XPath 2.0及以上版本才支持的比较运算符。XSLT 1.0对应的是XPath 1.0,不识别gt,需要用标准的>运算符替代。
解决办法
将断言表达式中的gt替换为>,修改后的代码如下:
from io import StringIO from lxml import etree, isoschematron f = StringIO( """\ <schema xmlns="http://purl.oclc.org/dsdl/schematron" > <pattern id="origDate"> <title>Original date rule</title> <rule context="Total"> <assert test="@calendar and (@when or @notBefore or @notAfter or @from or @to) and string-length(normalize-space(string())) > 0">A test rule.</assert> </rule> </pattern> </schema> """ ) sct_doc = etree.parse(f) schematron = isoschematron.Schematron(sct_doc)
修改后,表达式就能被lxml的XSLT 1.0引擎正确编译,验证流程可正常运行。
内容的提问来源于stack exchange,提问作者Andrew Dunning
相关产品推荐
相关产品推荐

