Search code examples
xmlxslt

How does the current() method works in xslt and what its effects are


How can I understand the current() in xslt 1.0?

Documentation:

enter image description here

xml

<xml>
  <listitems status="Yes" id="13" />
  <listitems status="No" id="12" />
</xml>

xsl

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="1.0">
  
  <xsl:output method="text"/>

  <xsl:template match="listitems">
    <!---The effects of using the period vs using current() -->
      <xsl:value-of select="//xml/listitems[@status=current()/@id]" />
  </xsl:template>

  <xsl:template match="listitems">
    <xsl:value-of select="@status"/>
  </xsl:template>
  
</xsl:stylesheet>

I'd be interested in a smaller example that can demo this better.


Solution

  • You are getting both "yes" and "no" in your output not because of the use of . or current(), but because you have two templates in your XSLT that match listitems

    <xsl:template match="listitems">
    

    This is an error according to the XSLT specification at http://www.w3.org/TR/xslt/#conflict....

    It is an error if this [The Conflict Resolution for Template Rules] leaves more than one matching template rule. An XSLT processor may signal the error; if it does not signal the error, it must recover by choosing, from amongst the matching template rules that are left, the one that occurs last in the stylesheet.

    In your case, the XSLT processor is simply handing the last template in the stylesheet, which will output both "yes" and "no". If you delete the first template, you would get the same results.

    If you want to see a case where . and current() are different, consider this XML

    <xml>
      <lists>
          <listitems status="Yes" id="13" />
          <listitems status="No" id="12" />
      </lists>
      <tests>
         <test name="Bob" testid="1" itemid="13" />
         <test name="Kate" testid="2" itemid="12" />
      </tests>
    </xml>
    

    And this XSLT

    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
      <xsl:output method="text"/>
    
      <xsl:template match="/*">
          <xsl:apply-templates select="tests" />
      </xsl:template>
    
      <xsl:template match="test">
        <xsl:value-of select="./@name" />
        <xsl:text> - </xsl:text>
        <!-- In this line, "." and "current()" are the same -->
        <xsl:value-of select="current()/@testid" />
        <xsl:text> - </xsl:text>
        <!-- In this line, they are not the same. Only "current()" will give the result needed -->
        <xsl:value-of select="//xml/lists/listitems[@id = current()/@itemid]/@status" />
      </xsl:template>
    </xsl:stylesheet>
    

    So, in this line, the current() function is being used in a condition that applies to a node

    <xsl:value-of select="//xml/lists/listitems[@id = current()/@itemid]/@status" />
    

    current() refers to the current node that was matched by the template; namely test

    . refers to the "context" item, which in this case is the listitems element being selected.