Page 1 of 1

Schematron assert test cannot use let variable

Posted: Fri Jul 25, 2025 9:08 am
by david_himself
I have a schema (ODD converted to RelaxNG) for validating XML files with mixed content. Several of the Schematron tests seem to be uneconomical, for example this one to control the @who attribute of the change element:
[code]
<attDef ident="who" mode="change" usage="opt">
<constraintSpec ident="check-xmlid_change" scheme="schematron">
<constraint>
<sch:rule context="tei:change/@who">
<sch:let name="noteMakers"
value="//tei:editor/@xml:id | //tei:respStmt/@xml:id"/>
<sch:let name="plusHash"
value="for $maker in $noteMakers return concat('#', $maker)"/>
<sch:assert test=". = //tei:editor/concat('#', @xml:id) or . = //tei:respStmt/concat('#', @xml:id)"
role="error">Permissible values are "<sch:value-of select="$plusHash"/>".
</sch:assert>
</sch:rule>
</constraint>
</constraintSpec>[/code]

The let variable plusHash is only used to list the permissible values of @who in the error message. The assert test makes no use of plusHash but instead in effect repeats the steps that were used to create it. This seems clumsy. Is there a way of using the variable plusHash in the assert test that does not trigger an out-of-scope or other error?

Re: Schematron assert test cannot use let variable

Posted: Tue Jul 29, 2025 5:04 pm
by george
Hi David,

This is a TEI ODD/Schematron specific question. I expect that changing the ODD file to

Code: Select all

<sch:assert test=". = $plusHash" role="error">
will work as well.

Here it is a quick test.xml/test.sch example that shows this working:

Code: Select all

<?xml version="1.0" encoding="UTF-8"?>
<?xml-model href="test.sch" type="application/xml" schematypens="http://purl.oclc.org/dsdl/schematron"?>
<test>
    <change who="#george"/>
    <editor xml:id="george"/>
</test>

Code: Select all

<?xml version="1.0" encoding="UTF-8"?>
<sch:schema xmlns:sch="http://purl.oclc.org/dsdl/schematron" queryBinding="xslt2"
    xmlns:sqf="http://www.schematron-quickfix.com/validator/process">

    <sch:pattern>
        <sch:rule context="change/@who">
            <sch:let name="noteMakers" value="//editor/@xml:id | //other/@xml:id"/>
            <sch:let name="plusHash" value="for $maker in $noteMakers return concat('#', $maker)"/>
            <sch:assert test=". = $plusHash" role="error"> Permissible values are "<sch:value-of
                    select="$plusHash"/>". </sch:assert>
        </sch:rule>
    </sch:pattern>
</sch:schema>
Hope this helps,
George

Re: Schematron assert test cannot use let variable

Posted: Tue Jul 29, 2025 5:32 pm
by david_himself
Thanks, George. That was exactly what I had expected, but when I tried it the other day, the .rng file gave an out-of-scope or undefined error. Perhaps there was a typo I missed. Anyway, yes, works as desired/expected.