Search code examples
xsltxpathumbraco

XSLT & Xpath syntax > how to refer to an element in an 'outer' scope


I have the following working 100% correctly. However to satisfy my curiosity... is there a way to achieve the same without declaring the currentID variable? Is there some way to reference it from within the Xpath "test" condition?

The xpath query in the condition must refer to 2 @id attributes to see if they match.

  • the 'current' @id
  • each 'ancestor' @id

Here's the code:

<xsl:variable name="currentID" select="@id" />
<xsl:attribute name="class">
<xsl:if test="count($currentPage/ancestor::node [@id = $currentID])&gt;0">descendant-selected </xsl:if>
</xsl:attribute>

Solution

  • Since you select the $currentID from the context node:

    <xsl:variable name="currentID" select="@id" />
    

    you can use the current() function, which always refers to the XSLT context node:

    <xsl:attribute name="class">
      <xsl:if test="count($currentPage/ancestor::node[@id = current()/@id]) &gt; 0]">
        <xsl:text>descendant-selected </xsl:text>
      </xsl:if>
    </xsl:attribute>
    

    This way you don't need a variable.

    A few other notes:

    • I recommend using <xsl:text> like shown above. This gives you more freedom to format your code and avoid overly long lines.
    • You don't need to do a count() > 0, simply selecting the nodes is sufficient. If none exist, the empty node-set is returned. It always evaluates to false, while non-empty node-sets always evaluate to true.

    If you refer to nodes by @id regularly in your XSL stylesheet, an <xsl:key> would become beneficial:

    <xsl:key name="kNodeById" match="node" use="@id" />
    
    <!-- ... -->
    
    <xsl:attribute name="class">
      <xsl:if test="key('kNodeById', @id)">
        <xsl:text>descendant-selected </xsl:text>
      </xsl:if>
    </xsl:attribute>
    

    The above does not need current() since outside of an XPath predicate, the context is unchanged. Also, I don't count() the nodes, since this is redundant (as explained).