Page 1 of 1

Set global "Let" in embedded RelaxNG/Schematron

Posted: Wed Jan 16, 2019 7:15 pm
by Andreas
Hi,

I'd like to set a global Schematron sch:let-variable in an embedded Relax NG-Schema.

Since this isn't supported by the standard-implementation, I've tried follow the steps in post33302.html and to alter the RNG2Schtrn.xsl and add

Code: Select all


<sch:schema>
[...]
<xsl:for-each select="$schemas/sch:let">
<xsl:copy-of select="."/>
</xsl:for-each>
[...]
</sch:schema>
Unfortunatly it didn't work out.

Any suggetions how I could make this work?

Thanks and regards,

Andreas

Re: Set global "Let" in embedded RelaxNG/Schematron

Posted: Thu Jan 17, 2019 5:19 pm
by Andreas
I'm still working on this issue, hence the follow-up question:

Is it possible to see the result of RNG2Schtrn.xsl? Does Oxygen produce log-files?

The validation message doesn't give much information "Errors were reported during stylesheet compilation" isn't very helpful in this case.

Re: Set global "Let" in embedded RelaxNG/Schematron

Posted: Fri Jan 18, 2019 9:50 am
by tavy
Hello Andreas

We are using the standard Schematron implementation for compiling Schematron embedded in Relax NG-Schema. It seems that you are not allowed to add global variables.
You can define a Schematron sch:let-variable in one of the sch:patterns from the embedded Relax NG-Schema. If a variable is added as a child of a sch:patterns element, in the compiled stylesheet will be generated as a global variable.

To see how the compiled stylesheet look like, you can run the "ISO Schematron to XSLT (compile)" transformation scenario over the Relax NG-Schema. For this you need to: select the Relax NG-Schema file, press the "Configure Transformation Scenario" toolbar button, from the "Configure Transformation Scenario" dialog filter settings button (the top-right corner) select "Show all scenarios", then search for "ISO Schematron to XSLT (compile)" and run it.

Best Regards,
Octavian

Re: Set global "Let" in embedded RelaxNG/Schematron

Posted: Fri Jan 18, 2019 1:01 pm
by Andreas
Hello Octavian,

thanks for the answer!

I know that the standard Schematron doesn't allow me to set global let-variables. That's why I changed the Code in "RNG2Schtrn.xsl" (Change under *NEW*)

Code: Select all


<xsl:template name="outputRNG">
<xsl:param name="schemas"/>
<!-- -->
<xsl:choose>
<xsl:when test="$schemas//iso:*">
<iso:schema>
<!-- disabled code-->
<!--<xsl:attribute name="queryBinding" select="if ($defaultQueryBinding) then $defaultQueryBinding else 'xslt2'"/>-->
<!-- Hardcoded xslt2 -->
<xsl:attribute name="queryBinding" select="'xslt2'"/>
<!-- get header-type elements - eg title and especially ns -->
<!-- title (just one) -->
<xsl:apply-templates mode="copyAndAddLocationAttributes" select="($schemas//iso:title)[1]"/>

<!-- Get the XSL and SQF elements -->
<xsl:call-template name="getXSLSQFInRNG">
<xsl:with-param name="schemas" select="$schemas"/>
</xsl:call-template>

<!-- get remaining schematron schema children -->
<!-- get non-blank namespace elements, dropping duplicates -->
<xsl:for-each select="$schemas//iso:ns">
<xsl:if test="generate-id(.) = generate-id($schemas//iso:ns[@prefix = current()/@prefix][1])">
<xsl:apply-templates mode="copyAndAddLocationAttributes" select="."/>
</xsl:if>
</xsl:for-each>
<xsl:apply-templates mode="copyAndAddLocationAttributes" select="$schemas//iso:phase"/>
<xsl:apply-templates mode="copyAndAddLocationAttributes" select="$schemas//iso:pattern"/>
<xsl:variable name="allDiagnostics" select="$schemas//iso:diagnostics/*"/>
<xsl:if test="count($allDiagnostics) > 0">
<iso:diagnostics>
<xsl:apply-templates mode="copyAndAddLocationAttributes" select="$allDiagnostics"/>
</iso:diagnostics>
</xsl:if>
</iso:schema>
</xsl:when>
<xsl:otherwise>
<sch:schema>
<!-- get header-type elements - eg title and especially ns -->
<!-- title (just one) -->
<xsl:apply-templates mode="copyAndAddLocationAttributes" select="($schemas//sch:title)[1]"/>

<!-- Get the XSL and SQF elements -->
<xsl:call-template name="getXSLSQFInRNG">
<xsl:with-param name="schemas" select="$schemas"/>
</xsl:call-template>

<!-- get remaining schematron schema children -->
<!-- get non-blank namespace elements, dropping duplicates -->
<xsl:for-each select="$schemas//sch:ns">
<xsl:if test="generate-id(.) = generate-id($schemas//sch:ns[@prefix = current()/@prefix][1])">
<xsl:apply-templates mode="copyAndAddLocationAttributes" select="."/>
</xsl:if>
</xsl:for-each>
<!-- *NEW* global variable *NEW* -->
<xsl:for-each select="$schemas/sch:let">
<xsl:copy-of select="."/>
</xsl:for-each>
<xsl:apply-templates mode="copyAndAddLocationAttributes" select="$schemas//sch:phase"/>
<xsl:apply-templates mode="copyAndAddLocationAttributes" select="$schemas//sch:pattern"/>
<xsl:variable name="allDiagnostics" select="$schemas//sch:diagnostics/*"/>
<xsl:if test="count($allDiagnostics) > 0">
<sch:diagnostics>
<xsl:apply-templates mode="copyAndAddLocationAttributes" select="$allDiagnostics"/>
</sch:diagnostics>
</xsl:if>
</sch:schema>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
Running "ISO Schematron to XSLT (compile)" confirms, that the global-let isn't set.

Re: Set global "Let" in embedded RelaxNG/Schematron

Posted: Tue Jan 22, 2019 12:29 pm
by Andreas
Are there any further ideas out there, why the new code wouldn't let me set a global variable?

Re: Set global "Let" in embedded RelaxNG/Schematron

Posted: Fri Jan 25, 2019 6:29 pm
by adrian
Hi,

Did you read the entire "Further development on schematron" thread (post33302.html)?
There are a couple of gotchas there.
You can't just patch a single XSL file via the lib/endorsed folder. Everything that is referred relatively by that XSL must also be included with the patch.
Note also the alternative solution using XML catalogs.

If you want to debug your XSLT changes first, duplicate the "ISO Schematron to XSLT (compile)" scenario and adjust it to run with your XSLT patches. Note that you need a folder with the entire set of stylesheets with the patches in place.

Regards,
Adrian