Search code examples
xsltsequencexslt-2.0functx

Find value in sequence using XSL


I want to check if a value exists in a sequence defined as

<xsl:variable name="some_seq" select="/root/word[@optional='no']/text()"/>

In the past, I've had success with Priscilla Walmsleys function. For clarity, I reproduce it here as follows:

<xsl:function name="functx:is-value-in-sequence" as="xs:boolean">
    <xsl:param name="value" as="xs:anyAtomicType?"/>
    <xsl:param name="seq" as="xs:anyAtomicType*"/>
    <xsl:sequence select="$value=$seq"/>
</xsl:function>

However, this time I need to make a case-insensitive comparison, and so I tried to wrap both $value and $seq with a lower-case(). Obviously, that didn't help much, as $seq is a sequence and lower-case() takes only strings.

Question: what is the best way to either 1) construct a sequence of lower-case strings, or 2) make a case-insensitive comparison analogous to $value=$seq above? TIA!


Solution

  • Question: what is the best way to either 1) construct a sequence of lower-case strings

    Not many people realize that you can use a function as the last location step in an XPATH 2.0 expression.

    You can create a sequence of lower-case() string values with this expression:

    /root/word[@optional='no']/text()/lower-case(.)
    

    or 2) make a case-insensitive comparison analogous to $value=$seq above?

    Using that strategy, you can define a custom function that compares the lower-case() value of the $value and each string value in the $seq:

    <xsl:function name="functx:is-value-in-sequence" as="xs:boolean">
        <xsl:param name="value" as="xs:anyAtomicType?"/>
        <xsl:param name="seq" as="xs:anyAtomicType*"/>
        <xsl:sequence select="some $word in $seq/lower-case(.) 
                                   satisfies ($word = $value/lower-case(.))"/>
    </xsl:function>