EM Engine Manual EM Engine Manual EM

Changing xsl:key to use contains function

48 views Asked by At

I have a small lookup file, internal_docnbr_titles.xml:

<custom-lookup>
        <document number="121212">
            <title>Engine Manual</title>
            <aka>EM</aka>
        </document>
        <document number="333333">
            <title>Cleaning, Inspection, and Repair Manual</title>
            <aka>CIR</aka>
        </document>
        <document number="222222">
            <title>Engine Illustrated Parts Catalog</title>
            <aka>EIPC</aka>
        </document>
        <document number="444444">
            <title>Illustrated Tool and Equipment Manual</title>
            <aka>ITEM</aka>
        </document>
</custom-lookup>

I am accessing the title with this key and sequence:

<xsl:variable name="dictionary" select="doc('internal_docnbr_titles.xml')/custom-lookup" as="element()" />
<xsl:key name="referenced-by-docnbr" match="*" use="@number"/>
<xsl:sequence select="key('referenced-by-docnbr',$docnbr, $dictionary)/title" />

But $docnbr might have a suffix attached that I can ignore for lookup purposes, so I would like to change the key to use the contains() function. (@number should always be found in a $docnbr)

So how would I rewrite the key so it will work like this:

<xsl:sequence select="$dictionary/document[contains($docnbr,@number)]/title

I've tried variations of:

<xsl:key name="referenced-by-docnbr" match="*[contains(.,@number)]" use="@number"/>

But that doesn't return anything.

EDIT:

I already had this sequence in a function so I wrapped around Martin's function:

<xsl:function name="fn:get-manual-title" as="xs:string?">
            <xsl:param name="docnbr" as="xs:string?"/>              
           
            <xsl:sequence select="fn:lookup($docnbr)/title" /></xsl:function>

<xsl:function name="fn:lookup" as="element(document)*" cache="yes" new-each-time="no">
            <xsl:param name="docnbr" as="xs:string?"/>
            <xsl:sequence select="$dictionary/document[contains($docnbr,@number)]"/>
        </xsl:function>

EDIT:

I kept Martin's solution but the problem was the key didn't have any context. Change it to <xsl:key name="referenced-by-docnbr" match="*[matches(@number,'^'|| $gek,'i')]" use="@number"/> where $gek is a global variable, then it works.

1

There are 1 answers

6
Martin Honnen On

You could try to use a "memory" function (declare some namespace e.g. xmlns:mf="http://example.com/mf")

<xsl:function name="mf:lookup" as="element(document)*" cache="yes" new-each-time="no">
  <xsl:param name="docnbr" as="xs:string"/>
  <xsl:sequence select="$dictionary/document[contains($docnbr,@number)]"/>
</xsl:function>

then instead of <xsl:sequence select="key('referenced-by-docnbr',$docnbr, $dictionary)/title" /> try e.g. <xsl:sequence select="mf:lookup($docnbr)/title" />