schematron icon indicating copy to clipboard operation
schematron copied to clipboard

Creates invalid stylesheet if attribute value templates are used in foreign elements

Open nkutsche opened this issue 6 years ago • 3 comments

Hi,

the skeleton creates an invalid stylessheet for this schema:

<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="any-context">
            <!--  do some test  -->
            <sqf:fix id="fix">
                <sqf:description>
                    <sqf:title>Sample fix</sqf:title>
                </sqf:description>
                <sch:let name="regex" value="'some regex'"/>
                <sqf:stringReplace match="." regex="{$regex}" select="'replacement'"/>
            </sqf:fix>
        </sch:rule>
    </sch:pattern>
</sch:schema>

The variable is not compiled as xsl:variable but the attribute value template is copied as it is, so the error is:

Error at sqf:stringReplace on line 197 column 87 of test.xsl:
  XPST0008: XPath syntax error at char 7 on line 197 in {{$regex}}:
    Variable $regex has not been declared
Failed to compile stylesheet. 1 error detected.

I think the problem is not that the variable is not compiled, but that the attribute value template is copied unchanged.

A workaround is, to add a global dummy variable with the same name:

<sch:schema xmlns:sch="http://purl.oclc.org/dsdl/schematron" queryBinding="xslt2"
    xmlns:sqf="http://www.schematron-quickfix.com/validator/process">
      <sch:let name="regex" value="'dummy'"/>

nkutsche avatar Mar 04 '19 12:03 nkutsche

The provided schema is not a valid Schematron document: The sch:let appears inside the sqf:fix, this is forbidden by the schema in Annex A.

foreign = foreign-attributes, foreign-element*
foreign-empty = foreign-attributes
foreign-attributes = attribute * - (local:* | xml:*) { text }*
foreign-element =
     element * - sch:* {
         (attribute * { text }
          | foreign-element
          | schema
          | text)*
     }

That's why the variable is not bound and adding a variable helps.

dmj avatar Mar 06 '19 11:03 dmj

As I wrote:

I think the problem is not that the variable is not compiled, but that the attribute value template is copied unchanged.

The QF could also contain a sqf:param or sqf:user-entry element:

<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="any-context">
            <!--  do some test  -->
            <sqf:fix id="fix">
                <sqf:param name="regex" default="'some regex'"/>
                <sqf:description>
                    <sqf:title>Sample fix</sqf:title>
                </sqf:description>
                <sqf:stringReplace match="." regex="{$regex}" select="'replacement'"/>
            </sqf:fix>
        </sch:rule>
    </sch:pattern>
</sch:schema>

In this case it is a valid Schematron document, but the error is the same.

I know, that this may a conflict of use cases, because if you escape attribute values of all foreign elements, you are not able to use them any more. So one possible solution would also be, to do not have just a switch for allowing/disallowing foreign elements, but to be able to give a list of namespaces of allowed/disallowed foreign elements.

nkutsche avatar Mar 08 '19 11:03 nkutsche

Okay, now I get it. I would extend the API with a process-foreign template that by default copies the elements if allow-foreign is true and let a user override this callback if the foreign elements need special treatment.

dmj avatar Mar 09 '19 09:03 dmj