An intro to using match templates in Umbraco

Written by Chriztian Steinmeier.
Got comments? I’m @greystate on Twitter. ← Back to Article Index

This is kind of a follow-up to my session at Codegarden ‘10, which was called XSLT beyond <for-each> — I talked about the advantages of using match templates and the apply-templates instruction instead of wrapping everything in a for-each instruction.

Umbraco MVP Warren Buckley suggested I took a couple of common Umbraco scenarios and rewrote them using templates instead of the for-each approach.

As always, the techniques discussed are applicable to any XSLT file, though I’m showing this in the context of Umbraco.

Code samples are shown for the new 4.5 XML Schema; but hey, if you’d like to view them using the old 4.0 Legacy XML Schema syntax, you can just click here to toggle display style...

Let’s start with the vanilla “List Sub Pages From Current Page” you get from a clean 4.5 install, and see what we can come up with:

Original

The first thing to do when converting this, would be to extract a template from the contents of the <xsl:for-each>, and replace the (now empty) <xsl:for-each> with a single apply-templates instruction using the same select attribute:

Step 1: Extract template

Next up, we eliminate the check for the value of umbracoNaviHide — a key point in this approach is to have something like that handled automatically, which we can do with an empty template:

So there you have it - a simple set of templates to replace the original—however, there are some real benefits to gain by specifying the document types you actually need, instead of just doing this generic thing. And I’ll walk you through that now.

Customizing for your particular needs

So, let’s see what we can do in a more defined environment—Let’s say we have two structures in our content that we’d need to render with this macro: News & Events.

We create four document types and use the Structure tab to enable creation in this type of hierarchy:

Now that it’s easy to know the containers from the items (by their names) we’ll put the <ul> creation inside a template matching those (you can match more than one element using a pipe character), and the <li> creation will be handled in the item template:

Step 3: Naming things

So this is now a nice macro that can be used on either of the News or Events pages, but what about the individual NewsItem and Event pages, can’t we support those in this too? (Of course the answer is “We can!”)

The trick lies within the template for the root node (the root node in XSLT is the one matching “/”); if we can change the select attribute to somehow always select the News or Events node, depending on which section we’re on, the templates we’ve already created will continue to work their magic.

In other words: We need to use the ancestor-or-self:: axis to select either the current page if it’s one of ‘News’ or ‘Events’, or any ancestor that’s a ‘News’ or ‘Events’ element.

(If you’re getting queezy when someone mentions axes in XSLT you should consult the doctor :-)

Step 4: Making it even more useful

As a final touch, let’s make sure we mark a news/event item if it’s the current page being rendered, by attaching the CSS class “selected”. We’ll also add an id to the <ul> to be able to style these lists individually. (The translate() function used here is what I call a “poor man’s lowercase” because it only targets specific uppercase characters of the elementnames.)

Step 5: Adding CSS hooks

Why are you adding the class attribute to the <li> and not the <a>?

I add the class on the list item and not the anchor because CSS selectors aren’t as smart as XPath selectors.

If I’d put the class on the anchor and I needed to style the list item differently, I would have no way to select the list item based on the class name of the anchor, but this way I can select either the list item with the "selected" class, or the anchor element that’s inside a list item with that class (or both).

That’s all folks, let’s have a final look at the whole thing:

Step 6: The final XSLT file

I hope you found it useful and that you’ve been pushed toward having yet another tool in your XSLT belt (BTW: I’d really like to get my hands on one of those... and smoke monsters...)