List based Menu - XSLT

26 May 2009 by Administrator

List based Menu - XSLT

Its rare to build a site which doesn't have some kind of navigation structure. This is an example of a nice bit of re-usable XSLT code to build site navigation. In our parent documents we have a two fields, one called navMainName and another called navMainSort. When a document has text in the 'navMainName' field, we include it in the navigation.

This XSLT also adds an 'active' to the class of the area of the site the user is browsing, using some CSS you can apply a different style to this.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xsl:stylesheet [
    <!ENTITY nbsp "&#x00A0;">
]>
<xsl:stylesheet
    version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxml="urn:schemas-microsoft-com:xslt"
    xmlns:umbraco.library="urn:umbraco.library"
    exclude-result-prefixes="msxml umbraco.library">


    <xsl:output method="xml" omit-xml-declaration="yes"/>
    <xsl:param name="currentPage"/>
    <xsl:template match="/">

      <!-- Request the value for siteRoot, and define it as a variable -->
      <xsl:variable name="siteRoot">
        <xsl:value-of select="$currentPage/ancestor::root/node/@id"/>
      </xsl:variable>

      <ul>
        <!-- Static List item for siteRoot (e.g. Home) -->
        <li>
          <a>
            <xsl:attribute name="class">
              <xsl:if test="$currentPage/@id = $siteRoot">
                active
              </xsl:if>
            </xsl:attribute>
            <xsl:attribute name="href">/</xsl:attribute>
            home
          </a>
          </li>
        <!-- Select each node which is a child of site root -->
        <xsl:for-each select="$currentPage/ancestor::root/node/node">
          <!-- Sort this data by nav Sort Order, defined on docType -->
          <xsl:sort select="string(data[@alias= 'navMainSort'])" order="ascending" />
          <!-- Pick the documents which have a tabName, and build a menu from them -->
          <xsl:choose>
            <xsl:when test="string(data[@alias= 'navMainName']) != ''">
              <li>
                <a>
                  <xsl:attribute name="class">
                    <!-- Compare ID to determine which page is active, using ancestor-self::node allows for sub pages! ;) Neat ay! -->
                    <xsl:if test="$currentPage/ancestor-or-self::node/@id = current()/@id">
                      active
                    </xsl:if>
                  </xsl:attribute>
                  <xsl:attribute name="href">
                    <xsl:value-of select="umbraco.library:NiceUrl(@id)"/>
                  </xsl:attribute>
                  <xsl:value-of select="data[@alias= 'navMainName']" />
                </a>
              </li>
            </xsl:when>
            <xsl:otherwise>
            </xsl:otherwise>
          </xsl:choose>
        </xsl:for-each>        
      </ul>

    </xsl:template>

</xsl:stylesheet>

Hopefully thats a useful bit of reusable code for you. (: Lau