Breadcrumbs in Umbraco 4.5

Working on a new website using the new Umbraco 4.5 (with the new xml schema), I had to write a new Breadcrumb xslt.

So, let’s see how we can handle this feature:

First, I’m assuming the HTML structure I wish at the end:

<div id="breadcrumb">
  <ul>
    <li>
      <a href="/" title="Home">Home</a>
    </li>
    <li>
      <a href="/parent.aspx" title="Parent">Parent</a>
    </li>
    <li>Current Page</li>
  </ul>
</div>

I’m assuming too my root DocumentType (the homepage one) is called “CommonHomePage” and my homepage url is the relative “/”.

Let’s begin with the “HOME” item we should manage in a different way than others:

        <li>
          <xsl:choose>
            <xsl:when test="$currentPage/ancestor-or-self::CommonHomePage/@id = $currentPage/@id">
              <xsl:value-of select="umbraco.library:GetDictionaryItem('Home')" />
            </xsl:when>
            <xsl:otherwise>
              <a href="/" title="{umbraco.library:GetDictionaryItem('Home')}">
                <xsl:value-of select="umbraco.library:GetDictionaryItem('Home')" />
              </a>
            </xsl:otherwise>
          </xsl:choose>
        </li>

With this piece of code, you’ll get Home with or without link based on current location.
Now you should keep the “Home”-code, we will use it later.

Next, I will create a recursive xsl template:

  <xsl:template name="innerNode">
    <xsl:param name="node"/>
        <xsl:for-each select="$node/*[@isDoc]">
          <xsl:if test="./descendant::*/@id = $currentPage/@id or ./@id = $currentPage/@id">
            <li>
              <xsl:choose>
                <xsl:when test="not(./@id = $currentPage/@id)">
                  <a href="{umbraco.library:NiceUrl(@id)}" title="{@nodeName}">
                    <xsl:value-of select="@nodeName" />
                  </a>
                </xsl:when>
                <xsl:otherwise>
                  <xsl:value-of select="@nodeName" />
                </xsl:otherwise>
              </xsl:choose>
            </li>
          </xsl:if>
          <xsl:call-template name="innerNode">
            <xsl:with-param name="node" select="."/>
          </xsl:call-template>
        </xsl:for-each>
  </xsl:template>

Now we can call this template from the “/” template:

  <xsl:template match="/">
    <div id="breadcrumb">
      <ul>
        <xsl:call-template name="innerNode">
          <xsl:with-param name="node" select="$currentPage/ancestor-or-self::CommonHomePage"/>
        </xsl:call-template>
      </ul>
    </div>
  </xsl:template>

And now it’s time to put the “Home” piece of code, so this is the full code:

><?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xsl:stylesheet [
  <!ENTITY nbsp " ">
]>
<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="/">
    <div id="breadcrumb">
      <ul>
        <li>
          <xsl:choose>
            <xsl:when test="$currentPage/ancestor-or-self::CommonHomePage/@id = $currentPage/@id">
              <xsl:value-of select="umbraco.library:GetDictionaryItem('Home')" />
            </xsl:when>
            <xsl:otherwise>
              <a href="/" title="{umbraco.library:GetDictionaryItem('Home')}">
                <xsl:value-of select="umbraco.library:GetDictionaryItem('Home')" />
              </a>
            </xsl:otherwise>
          </xsl:choose>
        </li>
        <xsl:call-template name="innerNode">
          <xsl:with-param name="node" select="$currentPage/ancestor-or-self::CommonHomePage"/>
        </xsl:call-template>
      </ul>
    </div>
  </xsl:template>

  <xsl:template name="innerNode">
    <xsl:param name="node"/>
        <xsl:for-each select="$node/*[@isDoc]">
          <xsl:if test="./descendant::*/@id = $currentPage/@id or ./@id = $currentPage/@id">
            <li>
              <xsl:choose>
                <xsl:when test="not(./@id = $currentPage/@id)">
                  <a href="{umbraco.library:NiceUrl(@id)}" title="{@nodeName}">
                    <xsl:value-of select="@nodeName" />
                  </a>
                </xsl:when>
                <xsl:otherwise>
                  <xsl:value-of select="@nodeName" />
                </xsl:otherwise>
              </xsl:choose>
            </li>
          </xsl:if>
          <xsl:call-template name="innerNode">
            <xsl:with-param name="node" select="."/>
          </xsl:call-template>
        </xsl:for-each>
  </xsl:template>
</xsl:stylesheet>

We have $node/*[isDoc] because the new XML schema.
Each child of $node now have as its nodename its alias. The empty attribute isDoc ensured it is a Document-Node, and not a Property-node.

Leave a Reply

*