Comparing multiple strings in Schematron

Questions about XML that are not covered by the other forums should go here.
shudson310
Posts: 156
Joined: Sat Feb 26, 2005 12:09 am
Location: USA
Contact:

Comparing multiple strings in Schematron

Post 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?
Scott Hudson
Staff Content Engineer
Site: docs.servicenow.com
shudson310
Posts: 156
Joined: Sat Feb 26, 2005 12:09 am
Location: USA
Contact:

Re: Comparing multiple strings in Schematron

Post 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.
Scott Hudson
Staff Content Engineer
Site: docs.servicenow.com
tavy
Posts: 365
Joined: Thu Jul 01, 2004 12:29 pm

Re: Comparing multiple strings in Schematron

Post 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
Octavian Nadolu
<oXygen/> XML Editor
http://www.oxygenxml.com
shudson310
Posts: 156
Joined: Sat Feb 26, 2005 12:09 am
Location: USA
Contact:

Re: Comparing multiple strings in Schematron

Post by shudson310 »

I was close, but just not getting it quite right.

That did it. Thanks, so much, Octavian!
Scott Hudson
Staff Content Engineer
Site: docs.servicenow.com
shudson310
Posts: 156
Joined: Sat Feb 26, 2005 12:09 am
Location: USA
Contact:

Re: Comparing multiple strings in Schematron

Post 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.
Scott Hudson
Staff Content Engineer
Site: docs.servicenow.com
tavy
Posts: 365
Joined: Thu Jul 01, 2004 12:29 pm

Re: Comparing multiple strings in Schematron

Post 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
Octavian Nadolu
<oXygen/> XML Editor
http://www.oxygenxml.com
Post Reply