Search code examples
xmlxsltxpathxslt-1.0descendant

Why //descendant is evaluating siblings as well in this XSLT template?


I am curious why this XSLT :

    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
      <xsl:template match="/">
          <xsl:apply-templates select="//ca"/> 
      </xsl:template>
      
      
      <xsl:template match="ca">  
          <xsl:value-of select="."/>
          <xsl:value-of select="//cd"/> 
      </xsl:template>
    </xsl:stylesheet>  

over this XML document

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <!DOCTYPE a>
    <a>
      <b>
        <c>
          <ca>CA</ca>
          <cd>CD</cd>
        </c>   
      </b>  
    </a>

has the result: CACD

I'm mostly interested in why CD evaluates properly because I thought current context in a template is defined by match attribute, that is to say, ca in the second template. If that was correct, in the context of ca, with //cd, as far as I know, the XSLT processor should be searching by any descendant of ca of any level with name cd.

cd is a sibling of ca, so I am very confused.

I would appreciate any help which sheds light on this.

Thank you in advance.


Solution

  • Use .//cd to select relative to the context node, a path starting with / always selects starting at the document node/root node, i.e. //cd is /descendant-or-self::node()/cd.