Page 1 of 1

Comparing multiple strings in Schematron

Posted: Wed Nov 25, 2020 2:21 am
by shudson310
I've got the following source:

Code: Select all

<dt><xref
                href="https://staging.example.com/example.html"
                format="html" scope="external" product="staging">My link 
                text</xref><xref
                href="https://production.example.com/example.html"
                format="html" scope="external" product="production">My link 
                text</xref><xref
                href="../example.xml"
                format="html" scope="external" product="local">Different link 
                text</xref></dt>
I need to create a Schematron to compare these values and report any different links.

I've got:

Code: Select all

<sch:pattern>
        <sch:rule context="*[count(xref = 3)]">
            <sch:let name="stag"><xsl:value-of select="normalize-space(xs:string(xref[@product='staging]))"/></sch:let>
            <sch:let name="prod"><xsl:value-of select="normalize-space(xs:string(xref[@product='production']))"/></sch:let>
            <sch:let name="local"><xsl:value-of select="normalize-space(xs:string(xref[@product='local']))"/></sch:let>
            <sch:assert id="myRule"
                test="($stag = $prod) and ($stag = $local)"
                role="error"
                sqf:fix="addPeriod">myRule: The text of this group of links must all match.</sch:assert>
        </sch:rule>
    </sch:pattern>
But I'm getting an error:
Engine name: ISO Schematron
Severity: warning
Description: Cannot convert string "My link\n..." to double
Start location: 889:41
As you can see, I tried to normalize spaces and ensure that they are strings.

Any ideas how to properly compare these strings in Schematron?

Re: Comparing multiple strings in Schematron

Posted: Wed Nov 25, 2020 5:43 am
by shudson310
OK, I have it closer, but now it is triggering on all of the links?

Code: Select all

<sch:pattern>
        <sch:rule context="*[count(xref = 3)]">
            <sch:let name="stag"><xsl:value-of select="normalize-space(xs:string(xref[@product='staging]))"/></sch:let>
            <sch:let name="prod"><xsl:value-of select="normalize-space(xs:string(xref[@product='production']))"/></sch:let>
            <sch:let name="local"><xsl:value-of select="normalize-space(xs:string(xref[@product='local']))"/></sch:let>
            <sch:assert id="myRule"
                test="('$stag' = '$prod') and ('$stag' = '$local')"
                role="error"
                sqf:fix="addPeriod">myRule: The text of this group of links must all match.</sch:assert>
        </sch:rule>
    </sch:pattern>
I only want to flag when the values are NOT equal.

Re: Comparing multiple strings in Schematron

Posted: Wed Nov 25, 2020 11:09 am
by tavy
Hello,
The context must be "*[count(xref) = 3]", and the variables must be without quotes.
I think the pattern should be something like this:

Code: Select all

<sch:pattern>
    <sch:rule context="*[count(xref) = 3]">
        <sch:let name="stag" value="normalize-space(xs:string(xref[@product='staging']))"/>
        <sch:let name="prod" value="normalize-space(xs:string(xref[@product='production']))"/>
        <sch:let name="local" value="normalize-space(xs:string(xref[@product='local']))"/>
        <sch:assert id="myRule"
            test="($stag = $prod) and ($stag = $local)"
            role="error">myRule: The text of this group of links must all match.</sch:assert>
    </sch:rule>
</sch:pattern>
Best Regards,
Octavian

Re: Comparing multiple strings in Schematron

Posted: Mon Nov 30, 2020 9:42 pm
by shudson310
I was close, but just not getting it quite right.

That did it. Thanks, so much, Octavian!

Re: Comparing multiple strings in Schematron

Posted: Tue Dec 01, 2020 12:10 am
by shudson310
Certain topics are now returning a fatal Schematron error:
A sequence of more than one item is not allowed as the value in 'cast as' expression (<xref>, <xref>)
My guess is that not all of these contain text to compare? I've tried adding:

Code: Select all

<sch:let name="empty"/>
            <sch:assert id="now014"
                test="($stag != $empty) and ($prod != $empty) and ($local != $empty) and ($stag = $prod) and ($stag = $local)"
                role="error">
but am still getting the error.

Re: Comparing multiple strings in Schematron

Posted: Thu Dec 03, 2020 6:10 pm
by tavy
Hello,

I don't know exactly what rule you want to add, and what is the structure you want to impose.
Probably this error occurs because you have two xref elements with the same value in the @product attribute.
I think first you need to check if all the xref elements are correct. You can check if you have a "staging", a "production, and a "local". The you can check also the text. Something like this:

Code: Select all

<sch:pattern>
    <sch:rule context="*[count(xref) = 3]">
        <sch:let name="staging" value="xref[@product='staging']"/>
        <sch:let name="production" value="xref[@product='production']"/>
        <sch:let name="local" value="xref[@product='local']"/>
        
        <sch:let name="stagingNo" value="count($staging)"/>
        <sch:let name="productionNo" value="count($production)"/>
        <sch:let name="localNo" value="count($local)"/>
        <sch:assert test="$stagingNo = 1">One staging xref is expected, are <sch:value-of select="$stagingNo"/></sch:assert>
        <sch:assert test="$productionNo = 1">One production xref is expected, are <sch:value-of select="$productionNo"/></sch:assert>
        <sch:assert test="$localNo = 1">One local xref is expected, are <sch:value-of select="$localNo"/></sch:assert>
      
        <sch:assert id="myRule"
            test="$stagingNo = 1 and $productionNo = 1 and $localNo = 1 and
            (normalize-space($staging) = normalize-space($production)) and (normalize-space($staging) = normalize-space($local))"
            role="error">myRule: The text of this group of links must all match.</sch:assert>
    </sch:rule>
</sch:pattern>
Best Regards,
Octavian