phax / ph-schematron

Java Schematron library that supports XSLT and native application
Apache License 2.0
110 stars 36 forks source link

pure: Variable defined in pattern are not resolved when used in rule context #142

Closed bertrand-lorentz closed 1 year ago

bertrand-lorentz commented 1 year ago

Trying to use the following Schematron in "pure" mode :

<schema xmlns="http://purl.oclc.org/dsdl/schematron" queryBinding="xslt2">
    <let name="topLevel" value="foo"/>
    <pattern id="1">
        <let name="inPattern" value="foo"/>
        <rule context="/*[$topLevel = 'foo']">
            <assert role="ERROR" test="$topLevel = $inPattern">message</assert>
        </rule>
        <rule context="/*[$inPattern = 'foo']">
            <assert role="ERROR" test="$topLevel = $inPattern">message</assert>
        </rule>
    </pattern>
</schema>

It fails for the second rule with the message below, because it can't resolve the $inPattern variable in the rule context.

It seems that variables defined inside the "pattern" are not considered when resolving variable reference in the context attribute. After quick look around in the code I found the following in PSXPathBoundSchema.java:

// Evaluate base node set for this rule
final String sRuleContext = aGlobalVariables.getAppliedReplacement (getValidationContext (aRule.getContext ()));

I think this should use aPatternVariables instead of aGlobalVariables

The error message and stacktrace:

21/02/2023 - 10:42:14.878 ERROR [pool-2-thread-1] oggingPSErrorHandler - [error] [PSRule] @ C:\...\validation.sch Failed to compile XPath expression in <rule>: '/*[$inPattern = 'foo']' 
(net.sf.saxon.trans.XPathException: Variable is used in XPath expression, but no JAXP VariableResolver is available)
        at net.sf.saxon.xpath.JAXPXPathStaticContext.bindVariable(JAXPXPathStaticContext.java:190)
        at net.sf.saxon.expr.parser.XPathParser.parseVariableReference(XPathParser.java:2438)
        at net.sf.saxon.expr.parser.XPathParser.parseBasicStep(XPathParser.java:2204)
        at net.sf.saxon.expr.parser.XPathParser.parseStepExpression(XPathParser.java:2101)
        at net.sf.saxon.expr.parser.XPathParser.parseRelativePath(XPathParser.java:2020)
        at net.sf.saxon.expr.parser.XPathParser.parsePathExpression(XPathParser.java:1982)
        at net.sf.saxon.expr.parser.XPathParser.parseSimpleMappingExpression(XPathParser.java:1996)
        at net.sf.saxon.expr.parser.XPathParser.parseUnaryExpression(XPathParser.java:1849)
        at net.sf.saxon.expr.parser.XPathParser.parseExprSingle(XPathParser.java:752)
        at net.sf.saxon.expr.parser.XPathParser.parseExpression(XPathParser.java:657)
        at net.sf.saxon.expr.parser.XPathParser.parsePredicate(XPathParser.java:2184)
        at net.sf.saxon.expr.parser.XPathParser.parsePredicate(XPathParser.java:2140)
        at net.sf.saxon.expr.parser.XPathParser.parseStepExpression(XPathParser.java:2110)
        at net.sf.saxon.expr.parser.XPathParser.parseRemainingPath(XPathParser.java:2060)
        at net.sf.saxon.expr.parser.XPathParser.parsePathExpression(XPathParser.java:1950)
        at net.sf.saxon.expr.parser.XPathParser.parseSimpleMappingExpression(XPathParser.java:1996)
        at net.sf.saxon.expr.parser.XPathParser.parseUnaryExpression(XPathParser.java:1849)
        at net.sf.saxon.expr.parser.XPathParser.parseExprSingle(XPathParser.java:752)
        at net.sf.saxon.expr.parser.XPathParser.parseExpression(XPathParser.java:657)
        at net.sf.saxon.expr.parser.XPathParser.parse(XPathParser.java:519)
        at net.sf.saxon.expr.parser.ExpressionTool.make(ExpressionTool.java:90)
        at net.sf.saxon.xpath.XPathEvaluator.compile(XPathEvaluator.java:201)
        at com.helger.schematron.pure.bound.xpath.PSXPathBoundSchema._compileXPath(PSXPathBoundSchema.java:109)
        at com.helger.schematron.pure.bound.xpath.PSXPathBoundSchema._createBoundPatterns(PSXPathBoundSchema.java:321)
        at com.helger.schematron.pure.bound.xpath.PSXPathBoundSchema.bind(PSXPathBoundSchema.java:472)
        at com.helger.schematron.pure.binding.xpath.PSXPathQueryBinding.bind(PSXPathQueryBinding.java:148)
        at com.helger.schematron.pure.bound.PSBoundSchemaCacheKey.createBoundSchema(PSBoundSchemaCacheKey.java:285)
        at com.helger.schematron.pure.bound.PSBoundSchemaCache.lambda$new$0(PSBoundSchemaCache.java:55)
        at com.helger.commons.cache.MappedCache.getFromCache(MappedCache.java:337)
        at com.helger.schematron.pure.SchematronResourcePure.createBoundSchema(SchematronResourcePure.java:286)
        at com.helger.schematron.pure.SchematronResourcePure.getOrCreateBoundSchema(SchematronResourcePure.java:301)
        at com.helger.schematron.pure.SchematronResourcePure.isValidSchematron(SchematronResourcePure.java:323)
        ...
phax commented 1 year ago

@bertrand-lorentz Thanks for pointing that out - you are totally right. Also the fix is exactly what is needed.

Quick info: afterwards another error occurs, because the pattern ID 1 is invalid:

2087 [main] ERROR com.helger.jaxb.validation.LoggingValidationEventHandler - JAXB [fatal_error] in obj: [ActivePattern@0x4a1e3ac1: document=null; documents=null; id=1; name=null; role=null; text=null] cvc-datatype-valid.1.2.1: '1' ist kein gültiger Wert für 'NCName'. (org.xml.sax.SAXParseException: cvc-datatype-valid.1.2.1: '1' ist kein gültiger Wert für 'NCName'.)
org.xml.sax.SAXParseException; lineNumber: 0; columnNumber: 0; cvc-datatype-valid.1.2.1: '1' ist kein gültiger Wert für 'NCName'.
    at java.xml/com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:204)
phax commented 1 year ago

Will be fixed in the upcoming 7.1.0 version (that is based on Saxon 12)

bertrand-lorentz commented 1 year ago

Quick info: afterwards another error occurs, because the pattern ID 1 is invalid:

The schematron is just a minimal example I quickly put together to reproduce the issue, so not a problem.

Thanks for the quick correction !

phax commented 1 year ago

Because Saxon 12 has some issues, I also backported all the changes and create a ph-schematron 7.0.1 release that is based on Saxon 11.4