Monday, March 8, 2010

XSL for getting a Sitecore path


Getting started with Sitecore is forcing me to come to grips with XSLT. Which is a gnarly beast. As I figure out how to do things simple and not so simple, I'll post them here, where I can find them.

First on the list--how to generate an item path.  Along the way, we'll cover recursion in XSLT, and how Sitecore   represents content in XML.


Let's start with Sitecore's representation of content. First, all items in the Sitecore content tree are represented as <item> elements, with a nested <fields> element.  Each item has a mixed case name (e.g. "Sitecore" or "Content") and a lower-case version of the name in the "key" attribute ("sitecore" or "content") plus GUIDs for the item and the template it is based on.  Putting this all together looks like this:

<item  id="11111111-111..." key="sitecore" name="sitecore" tid="(template guid)">
     <fields>
     <items .. . >
</item>
(More details on Sitecore's XML format can be found in Sitecore's XSL Cookbook)

So to represent a node of the Sitecore content tree, you want to use .  Using select="name(.)" will always return "item".

Now suppose you want to represent the path of an item like this:
/sitecore/content/Home/Our-Process/Resources-and-Goals
This can be done using a recursive template, by printing out the current node, and then calling the template again to represent its parent.  The trick is to check whether the node has a parent, which you can do with this bit of XPATH:
test="$node/parent::*"
Translated into English, this will be true if the current node has a parent node of any name.  The whole template looks like this:
  <xsl:template name="get-path"> 
    <xsl:param name="node" /> 
    <xsl:param name="use-sitecore-names" select="0" /> 
    <xsl:if test="$node/parent::*"> 
      <xsl:call-template name="get-path"> 
        <xsl:with-param name="node" select="$node/parent::*" /> 
        <xsl:with-param name="use-sitecore-names" select="$use-sitecore-names" /> 
      </xsl:call-template> 
    </xsl:if> 
    <xsl:text>/</xsl:text> 
    <xsl:choose> 
      <xsl:when test="$use-sitecore-names"> 
        <xsl:value-of select="$node/@name" /> 
      </xsl:when> 
      <xsl:otherwise> 
        <xsl:value-of select="name($node)" /> 
      </xsl:otherwise> 
    </xsl:choose> 
  </xsl:template>

A few additional notes:
  1. The use-sitecore-names parameter allows a choice between showing XML element names, and Sitecore content item names.  This allows the template to be useful in non-Sitecore contexts.  In XSLT, 0 resolves to false, 1 to true.
  2. The xsl:if statement only calls the template recursively if there is a parent.
  3. After the recusive call, the template writes the current node, preceded by a slash.

No comments:

Post a Comment