Search code examples
xmlxsltxpathxslt-2.0xpath-2.0

XSLT - check if all nodes of a sequence match a set of values


Using XSLT v2.0, how can I check that the text of all the selected nodes are matching some reference values?

For example, I select all H1 nodes. I want to make sure that all of them are either equal to "The title" or "A heading".

I've been trying to create a function for that:

<xsl:function name="is-valid" as="xs:boolean">
    <xsl:param name="seq" as="item()*" />
    <xsl:for-each select="$seq">
            <xsl:if test="not(matches(current()/text(),'The title|A heading'))">
                <!-- ??? -->           
            </xsl:if>
    </xsl:for-each>
</xsl:function>

I'm don't think this is the way to go in XSLT, but I can't find how to do this.

Any hint?


Solution

  • XSLT 2.0 has an every..satisfies construct that can help here:

    <xsl:function name="e:is-valid" as="xs:boolean">
      <xsl:param name="s" as="item()*" />
      <xsl:value-of select="every $i in $s satisfies $i=('The title', 'A heading')"/>
    </xsl:function>
    

    Here's a complete example:

    XML

    <?xml version="1.0" encoding="UTF-8"?>
    <r>
      <h1>Wrong title</h1>
      <h1>The title</h1>
      <h1>A heading</h1>
    </r>
    

    XSLT

    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet version="2.0" 
                    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                    xmlns:xs="http://www.w3.org/2001/XMLSchema"
                    xmlns:e="http://example.com/f">
    
      <xsl:template match="/">
        <xsl:message>
          <xsl:value-of select="e:is-valid(//h1)"/>
        </xsl:message>
      </xsl:template>
    
      <xsl:function name="e:is-valid" as="xs:boolean">
        <xsl:param name="s" as="item()*" />
        <xsl:value-of select="every $i in $s satisfies $i=('The title','A heading')"/>
      </xsl:function>
    
    </xsl:stylesheet>