Test to see if text contains a string from a list of values

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

Test to see if text contains a string from a list of values

Post by shudson310 » Fri Nov 06, 2020 5:05 am

I'm trying to create a Schematron rule that will check text nodes against a list of terms in an external document. Basically, I'm trying to see if writers included a product name directly in text instead of using a keyref in DITA.

I'm reading in my external document by:

Code: Select all

<sch:let name="keys"
        value="document('keys-common.ditamap')"/>
I need a test that will check to see if the text nodes contain one of the values from

Code: Select all

$keys//keyword
I can get an exact match using:

Code: Select all

<sch:let name="text" value="text()"/>
        <sch:report id="now001"
            test="$keys//keyword[normalize-space(.) =$text]"
            role="error">
But that only works if the entire node matches. I want to check if the phrase is contained within a larger set of text.

Trying something like this:

Code: Select all

test="$keys//keyword[contains($text, .)]" 
results in:
A sequence of more than one item is not allowed as the first argument of fn:contains() ("
", "
")

Any ideas?
Scott Hudson
Staff Content Engineer
Site: docs.servicenow.com

tavy
Posts: 281
Joined: Thu Jul 01, 2004 12:29 pm

Re: Test to see if text contains a string from a list of values

Post by tavy » Fri Nov 06, 2020 10:21 am

Hello Scott ,

I think that a solution can be to count the number of matched keys, then you can write also the matched keys in the assertion message. The pattern must look something like this:

Code: Select all

<sch:pattern>
    <sch:let name="keys" value="document('keys-common.ditamap')//keyword"/>
    <sch:rule context="p">
        <sch:let name="text" value="text()"/>
        <sch:let name="matchedKeys" value="$keys[contains($text, normalize-space(.))]"/>
        <sch:report id="now001" test="count($matchedKeys) > 0" role="error">
            Text contains keywords: <sch:value-of select="$matchedKeys"/>
        </sch:report>
    </sch:rule>
</sch:pattern>
Best Regards,
Octavian
Octavian Nadolu
<oXygen/> XML Editor
http://www.oxygenxml.com

shudson310
Posts: 149
Joined: Sat Feb 26, 2005 12:09 am
Location: USA
Contact:

Re: Test to see if text contains a string from a list of values

Post by shudson310 » Fri Nov 06, 2020 7:19 pm

Unfortunately, I get this error:
A sequence of more than one item is not allowed as the first argument of fn:contains() ("Access to the ", " overview module is granted to a sp...")
Scott Hudson
Staff Content Engineer
Site: docs.servicenow.com

tavy
Posts: 281
Joined: Thu Jul 01, 2004 12:29 pm

Re: Test to see if text contains a string from a list of values

Post by tavy » Mon Nov 09, 2020 10:16 am

Hello Scott,

Yes, in case there are multiple text nodes in a paragraph the "text()" function will return a sequence of text nodes. You can replace the "$text" variable with the following one:

Code: Select all

<sch:let name="text" value="."/>
Best Regards,
Octavian
Octavian Nadolu
<oXygen/> XML Editor
http://www.oxygenxml.com

Post Reply