I am attempting to use an RNG schema to validate XML against RelaxNG and Schematron rules with lxml. This is a common arrangement for more complex forms of XML, such as TEI, but it is surprisingly difficult to find a reliable validator with minimal dependencies. I keep receiving lxml.etree.XSLTParseError
errors on test expressions that work elsewhere. Is there a way to work around this?
This is a minimal example, based on the lxml documentation:
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)
The full error message is 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'
.
Use >
instead of gt
.
gt
is in XPath 2.0 and later. 'lxml' is presumably working with XSLT 1.0 and XPath 1.0, which don't support gt
.
Compare https://www.w3.org/TR/1999/REC-xpath-19991116/#NT-RelationalExpr and https://www.w3.org/TR/xpath20/#doc-xpath-ComparisonExpr