user3629892
user3629892

Reputation: 3046

xslt 2.0: current() not working as expected

Given this input:

<?xml version="1.0"?><catalog>
   <book>
      <autho>Gambardella, Matthew</author>
   </book>
   <book>
      <author>Ralls, Kim</author>
   </book>
   </catalog>

and this XSLT 2.0 stylesheet

<?xml version="1.0"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/">
<out>
<xsl:apply-templates/>
</out>
</xsl:template>

<xsl:template match="catalog">

<xsl:for-each select="book">
<text>
Current node: <xsl:value-of select=" current()/name()"/>
Context node: <xsl:value-of select="./name()"/>
</text>
</xsl:for-each>
</xsl:template>

</xsl:stylesheet>

why is the output not:

<?xml version="1.0" encoding="UTF-8"?><out><text>
Current node: catalog
Context node: book</text><text>
Current node: catalog
Context node: book</text></out>

but instead:

<?xml version="1.0" encoding="UTF-8"?><out><text>
Current node: book
Context node: book</text><text>
Current node: book
Context node: book</text></out>

I thought current() refers back to the node the template matches and I can use it to always refer back to that node?

Upvotes: 1

Views: 232

Answers (1)

Kim Homann
Kim Homann

Reputation: 3229

It does make a difference whether you use . or current() when dealing with XPath expressions with square brackets. By using an opening square bracket, you change the context, and . will relate to the expression immediately before the brackets, whereas current() is not affected by the context change.

With <xsl:for-each>, things are different. It also changes the context, but . and current() are both affected.

The thing you want can be achieved by storing . in a variable before the for-each loop starts:

<?xml version="1.0"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/">
        <out>
            <xsl:apply-templates/>
        </out>
    </xsl:template>
    <xsl:template match="catalog">
        <xsl:variable name="context" select="."/>
        <xsl:for-each select="book">
            <text>
Current node: <xsl:value-of select="$context/name()"/>
Context node: <xsl:value-of select="./name()"/>
            </text>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

Upvotes: 2

Related Questions