phax / ph-schematron

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

XPath 2 variable substitution in Pure Schematron #91

Closed qligier closed 1 year ago

qligier commented 4 years ago

Hi, I'm trying to use the Pure Schematron validator but I've encountered an issue with variable substitution. The Schematron I deal with uses let statements with XPath 2 patterns, and an example of problematic rule is:

<rule>
  <let name="xsiLocalName"
       value="if (contains(@xsi:type, ':')) then substring-after(@xsi:type,':') else @xsi:type"/>
  <let name="xsiLocalNS"
       value="if (contains(@xsi:type, ':')) then namespace-uri-for-prefix(substring-before(@xsi:type,':'),.) else namespace-uri-for-prefix('',.)"/>
  <assert role="error"
          see="http://ehealthsuisse.art-decor.org/cdachemed-html-20180508T090351/tmp-1.3.6.1.4.1.19376.1.9.1.3.2-2018-01-11T130449.html"
          test="@nullFlavor or ($xsiLocalName='EIVL_TS' and $xsiLocalNS='urn:hl7-org:v3')">Error</assert>
</rule>

When the variables are resolved and replaced, the test becomes

@nullFlavor or (if (contains(@xsi:type, ':')) then substring-after(@xsi:type,':') else @xsi:type='EIVL_TS' and if (contains(@xsi:type, ':')) then namespace-uri-for-prefix(substring-before(@xsi:type,':'),.) else namespace-uri-for-prefix('',.)='urn:hl7-org:v3')

and Saxon fails to compile it (Unexpected token "if(" at start of expression). Now, if braces are added around when replacing variable names with their content, Saxon is able to compile the resulting test:

@nullFlavor or ((if (contains(@xsi:type, ':')) then substring-after(@xsi:type,':') else @xsi:type)='EIVL_TS' and (if (contains(@xsi:type, ':')) then namespace-uri-for-prefix(substring-before(@xsi:type,':'),.) else namespace-uri-for-prefix('',.))='urn:hl7-org:v3')

The validation with XSLT is working as expected. Do you have any idea on this issue? Thank you, Quentin

phax commented 4 years ago

I am afraid this seems to be the same as #88 Pure version does not handle "let" with variables correctly :(

qligier commented 4 years ago

Query language binding for XPath 2 states:

The let element should not be used.

Oh, so variables substitution as it's implemented should only work with simpler XPath 1 expressions?

What do you think about always adding braces when substituting XPath variables? It should improve support for more complex expressions without pejorating current support (at least to my current understanding)?

stale[bot] commented 4 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

qligier commented 4 years ago

Hi, I've been playing with that and have implemented a PoC inspired by the pure version to validate Schematron files, using Saxon as XQuery processor and avoiding all XSLT transformations. I think the main difference is that I don't substitute variables in the patterns but execute them with Saxon and inject the result in the following selectors. It works fine with the large Schematron files I'm dealing with, but I don't know what subset of XPath 2/XSLT is effectively used in it and if it could work with any Schematron file. Could it be of any help here? If not, I guess this issue can be closed.

phax commented 1 year ago

Closing this in favour of the newer #143 - tackle it there.