[Schematron] Trying to iterate over a map of key-values

Post here questions and problems related to editing and publishing DITA content.
TheLetterF
Posts: 2
Joined: Wed Aug 21, 2024 6:16 pm

[Schematron] Trying to iterate over a map of key-values

Post by TheLetterF »

Hi there,
I'm trying to convert Vale linter rules to Schematron checks. One that has me scratching my head is this:

https://github.com/splunk/vale-splunk-s ... rdList.yml

What I'm trying is to use an X-path function like this:

Code: Select all

<let name="patterns" value="map {
      '(?:UNIX|Linux)': '*nix',
      '(?:addon|add-On|Add-On|AddOn)': 'add-on|Add-on',
      '(?:addons|add-Ons|Add-Ons|AddOns)': 'add-ons|Add-ons',
      ...
Then I try doing this:

Code: Select all

<xsl:template match="/>
    <xsl:for-each select="map:keys($patterns)">
        <pattern>
            <rule context="//text()">
                <report test="matches(., ., 'i')" role="warning">
                    <xsl:value-of select="."/> should be replaced with <xsl:value-of select="map:get($patterns, .)"/>
                </report>
            </rule>
        </pattern>
    </xsl:for-each>
</xsl:template>
This is in a file with other patterns. When I try running Schematron from Oxygen, I get this message:

Code: Select all

Ambiguous rule match for /
Matches both "/" on line 233 of file:/Users/fferribenedetti/repos/schematron-rules/Rules/StyleGuide.xml
and "/" on line 212 of file:/Users/fferribenedetti/repos/schematron-rules/Rules/StyleGuide.xml
Any clue on why this happens? If I switch the context to //text() or text(), the rule doesn't trigger. The context of all other patterns is text().

The approach itself might as well be totally inadequate. Any advice is appreciated. FYI, this is for a CCMS, not for Oxygen (otherwise I would have used the Terminology check add-on).

Thanks!
tavy
Posts: 390
Joined: Thu Jul 01, 2004 12:29 pm

Re: [Schematron] Trying to iterate over a map of key-values

Post by tavy »

Hello,

A solution can be to create an XSLT function that applies the regular expression and verifies the text. Something like this:

Code: Select all

<?xml version="1.0" encoding="UTF-8"?>
<sch:schema xmlns:sch="http://purl.oclc.org/dsdl/schematron" queryBinding="xslt2"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:map="http://www.w3.org/2005/xpath-functions/map"
    xmlns:f="my.functions"
    xmlns:sqf="http://www.schematron-quickfix.com/validator/process">
    
    <sch:ns uri="my.functions" prefix="f"/>
    
    <sch:pattern>
        <sch:rule context="text()">
            <sch:let name="suggestion" value="f:getSuggestion(.)"/>
            <sch:report test="$suggestion" role="warning">
                <xsl:value-of select="$suggestion"/>
            </sch:report>
        </sch:rule>
    </sch:pattern>
    
    <xsl:function name="f:getSuggestion">
        <xsl:param name="text"/>
        <xsl:variable name="patterns" select="map {
            '(?:UNIX|Linux)': '*nix',
            '(?:addon|add-On|Add-On|AddOn)': 'add-on|Add-on',
            '(?:addons|add-Ons|Add-Ons|AddOns)': 'add-ons|Add-ons'}"
        />
        <xsl:for-each select="map:keys($patterns)">
            <xsl:if  test="matches($text, current(), 'i')">
                <xsl:value-of select="current()"/> should be replaced with <xsl:value-of select="map:get($patterns, current())"/>
            </xsl:if>
        </xsl:for-each>
    </xsl:function>
   
</sch:schema>
Best Regards,
Octavian
Octavian Nadolu
<oXygen/> XML Editor
http://www.oxygenxml.com
Post Reply