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.
