Search code examples
xslt-2.0

XSL:KEY Function for external file


I have an issue in key function, key function not running in following code.

my input is

XML (Keys.xml)

<?xml version="1.0" encoding="UTF-8"?>
<Keys>
    <Key year="2001" name="ABC"/>
    <Key year="2002" name="BCA"/>
</Keys>

XML to convert

<?xml version="1.0" encoding="UTF-8"?>
<p>
    <text> .. .. <key>ABC</key> ...</text>
    <text> .. .. <key>BCA</key> ...</text>
</p>

XSLT

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="2.0">
    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>
    <xsl:key name="keydata" match="*[name() = document('keys.xml')]/Keys/Key" use="@name"/>
    <xsl:template match="key">
        <xsl:copy>
            <xsl:attribute name="ref"><xsl:value-of select="key('keydata', .)/@year"/></xsl:attribute>
            <xsl:value-of select="."/>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

Output

<p>
    <text> .. .. <key ref="">ABC</key> ...</text>
    <text> .. .. <key ref="">BCA</key> ...</text>
</p>

Desired Ouput

<p>
    <text> .. .. <key ref="2001">ABC</key> ...</text>
    <text> .. .. <key ref="2002">BCA</key> ...</text>
</p>

Solution

  • This should work:

    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        version="2.0">
    
        <xsl:variable name="keys" select="document('keys.xml')" as="document-node()"/>
    
        <xsl:key name="keydata" match="Key" use="@name"/>
    
        <xsl:template match="node()|@*">
            <xsl:copy>
                <xsl:apply-templates select="node()|@*"/>
            </xsl:copy>
        </xsl:template>
    
        <xsl:template match="key">
            <xsl:copy>
                <xsl:attribute name="ref"><xsl:value-of select="$keys/key('keydata', current())/@year"/></xsl:attribute>
                <xsl:value-of select="."/>
            </xsl:copy>
        </xsl:template>
    </xsl:stylesheet>
    

    In the XSL specification, there's an example entitled "Example: Using Keys to Reference other Documents" that exactly matches your use case.

    This is the resulting document:

    <?xml version="1.0" encoding="UTF-8"?>
    <p>
        <text> .. .. <key ref="2001">ABC</key> ...</text>
        <text> .. .. <key ref="2002">BCA</key> ...</text>
    </p>