Overture The Complete Resource Center for Symphony

Looking for something?
Login to Overture
2006-09-13 02:35 A Symphony Walkabout

The templating system in Symphony utilizes pure XSLT. This article is meant to help Symphony users get through the beginning jitters of learning a new templating system. Like any other templating system, you will need to learn how to use it. What’s the difference between XSLT and a proprietary templating system?

Once you get a handle of XSLT, you’ll be amazed at how powerful the language is and what you can do with it. So let’s put those jitters aside and step into the realm of XSLT.

Where to Start

If you have ever been to the Symphony, in the literal sense, you might have noticed that there was a little more to it than just one man throwing his arms around. Similar to the way a Beethoven or Mozart masterpiece makes use of an orchestra, Symphony incorporates several web standards to orchestrate the sweet sound of success in launching a new site. Along your path to enlightenment, you’ll need to familiarize yourself with the basics of XML and XPath, in addition to your XSLT knowledge. If you’ve never been to the Symphony, here’s how it works in slightly geekish terms:

XML

XML is a markup language much like HTML and it describes the data. There is more to XML but you only need to be concerned with reading it. Let’s take a look at an example from Symphony.

<data>
    <categories>
        <category handle="announcement">
            <name>Announcement</name>
            <description>News, Important information and such.</description>
            <entry handle="all-the-way-from-australia">
                <time>08:13</time>
                <title>All the way from Australia</title>
                <author>Symphony Team</author>
                <excerpt>Here's a great big G'day from the Symphony team. We hope you enjoy Symphony as much as we have had developing it! Here in Australia, Summer comes at the end of the year and the team will be</excerpt>
                <comments>0</comments>
            </entry>
        </category>
        .
        .
        .
    </categories>
</data>

The partial XML data above is an example of what you might find when you add ?debug to the end of a Symphony URL on your front-end while logged in (it defaults to HTML output, so click XML ). The XML data will vary depending on what data sources are associated with the page you view. You can add and delete data sources by configuring a page’s settings.

OK, now that you have some XML to look at, let’s learn how to interpret it.

Enough about the family, that’s all you need to know about XML to get started with Symphony.

XPath

Lets go back to the Symphony for a moment. If XML were the sheet music, instruments play the notes much like XPath navigates the XML . XPath views elements and attributes in XML as nodes. There are seven types of nodes in XPath, but for now we are only concerned with elements and attributes. The relationships between elements in XML , as illustrated above, are the same in XPath.

XPath uses expressions to target different elements. Here’s a simple absolute XPath expression to get you acquainted.

/data/categories/category/name

In the previous XML data source example, the above XPath expression will select all child nodes of the name element. In expressions, data, categories, category, and name are referred to as steps and are separated by a /. Absolute expressions begin with a / and relative expressions do not. An expression never ends with / or //. You’ll need to understand XPath’s basic syntax to get started building your web site in Symphony.

Let’s take a look at some examples using the previous XML data source example and our newfound love of XPath syntax.

Remember that the value of an element can be “Announcement” in the case of //name and the value of an element can also be other elements, as is the case with //categories/category. Also, realistically speaking, there would likely be many category elements. An XPath expression would therefore return a node-set when an expression is met more than once.

Next up, predicates! Predicates are a powerful tool in XPath expressions. You can use them to find a specific node or a node based on a specific value. Predicates are essentially statements that evaluate to true or false. If the statement is true, the element is selected. Predicates are always surrounded by square brackets [ ]. You’ll need to know about operators to compare the values in your predicate, so here are a few common ones you’ll see in Symphony templates.

Let’s look at a few examples of predicates in action!

Did you know XPath has built-in functions?! You’ll find many extremely useful, others you will scratch your head and move on with your life. Let me introduce you to position(). If one of your expressions result in a node-set and you want to limit what is returned, you would use position() to return a value. position() will equate to a node’s position in the XML and in our case of the last predicate example, only return what satisfies the predicate.

You can have multiple comparisons by using and and or.

Time to kick it up a notch and move on to XSLT.

Deconstructing the default template

Oh hell, let’s go back to the Symphony. If XML were the sheet music and XPath were the instrument, XSLT would be the musician that actually makes it happen. XSLT transforms the XML data into markup for our browser with the help of XPath, much like a musician plays music for the audience with the help of an instrument.

Before you start looking at XSLT it’s important to understand how Symphony organizes templates. All of your templating will be organized into pages, utilities, masters (formally called Templates), and assets.

With the exception of assets, the rest contain XSLT templates. Pages, masters, and utilities will always contain at least <xsl:apply-templates/> or <xsl:template> or both elements.

Well, the best way to learn Symphony is hands-on. So, launch another browser window and start poking around. It might be handy to have several windows open (this article, page XML , page template). Let’s take a look at the master default template.

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN" doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" encoding="UTF-8" indent="yes" />
<xsl:template match="/">
    <html>
        <head>
            <title><xsl:value-of select="$website-name"/> - <xsl:value-of select="$title"/></title>
            <link rel="stylesheet" type="text/css" media="screen" href="{$root}/workspace/css/styles.css"/>
            <link rel="alternate" type="application/rss+<abbr>XML</abbr> " href="/rss/" />
        </head>

        <body>
            <h1><xsl:value-of select="$website-name"/><xsl:text> </xsl:text><small>Share the love</small></h1>

            <ul id="navigation"><xsl:call-template name="show-navigation"/></ul>

            <div id="content">
                <xsl:apply-templates/>
            </div>

            <div id="footer">Powered by Symphony. <a href="/rss/">RSS 2.0 Feed</a>.</div>
        </body>
    </html>  
</xsl:template> 
</xsl:stylesheet>

You shouldn’t need to worry too much about the first three lines in the master default template. The first line declares that this document is XML . The second more clearly defines it as a stylesheet. And the third line allows us to choose several output options. These three lines can virtually be copied from master template to master template. The stylesheet element has a closing tag, and more importantly it surrounds the master template’s juicy bits. If you look further down the code in the body section you’ll notice the <xsl:apply-templates/> element. This is where all page templates are inserted.

XSLT can have templates inside of other templates. This is what makes XSLT so flexible. Also between the body tags is a <xsl:call-template name="show-navigation"/> element. The template named show-navigation will be inserted at this point in the document. This particular instance has no closing tag because it does not pass any information to the template named show-navigation.

Symphony automatically creates several parameters for every page and as a result are global. To see what parameters have been created for each page, add ?debug to the end of a Symphony URL on your front-end while logged in and view the XSLT (this lists the appropriate page template and all utilities). The following is a list of the default parameters created for every page.

<xsl:param name="root" select="'http://lewis.textdriven.com/symphony'" />
<xsl:param name="current-page" select="'index'" />
<xsl:param name="page-title" select="'Home'" />
<xsl:param name="parent-page" select="'/'" />
<xsl:param name="today" select="'2006-02-07'" />
<xsl:param name="website-name" select="'Behold, Symphony'" />

These parameters will be extremely useful when you build your web site. They are accessed using the <xsl:value-of> element and have a prefix of $. If you are using the parameter in an attribute, such as href, then you must prefix the name with a $ and surround the whole thing with { }. If you are using the parameter in an XSLT attribute then you simply need to prefix the parameter name with $.

Let’s take a look at the show-navigation template, which has been organized into a navigation utility. One of the options on utility pages is the ability to associate a data source. The navigation utility has the navigation data source associated with it. The code introduces a couple new XSLT elements <xsl:choose> and <xsl:for-each>.

<xsl:template name="show-navigation">
    <xsl:for-each select="data/navigation/page">
        <xsl:choose>
            <xsl:when test="@handle = $current">
                <li><xsl:value-of select="title"/></li>
            </xsl:when>

            <xsl:when test="@handle = 'index' ">
                <li><a href="{$root}"><xsl:value-of select="title"/></a></li>
            </xsl:when>

            <xsl:otherwise>
                <li><a href="{$root}/{@handle}/"><xsl:value-of select="title"/></a></li>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:for-each>
</xsl:template>

The <xsl:choose> element tests to see if a test is true and selects the appropriate output. The XSLT processor will start at the beginning and test each <xsl:when> element until it reaches a test that is true. If no tests result true, then the <xsl:otherwise> element is chosen. You can have as many <xsl:when> elements as needed, but remember that the order is important because it will stop testing at the first test that is true. Notice the use of the <xsl:for-each> element which will apply what’s between its tags, <xsl:choose> element in this case, for each node (i.e. page). Without the <xsl:for-each> element, only the home page would be displayed in the navigation.

If you haven’t noticed already, the <xsl:for-each> element grabs a node-set made up of page elements from the XML. <xsl:value-of> is used once again, to get the value of the title element. This is a relative XPath expression because it is within the <xsl:for-each> element and acting upon the node-set that the <xsl:for-each> selected.

Let’s take a look at the page titled Category. These templates will be applied within the master template, between the body tags, when a user visits the category page. Symphony allows you to configure each page to your needs. Upon clicking on a page in the admin, you’ll notice on the right side you have the ability to associate different master templates with each page. Cool, eh? But wait, that’s not all! Click on the configure button just above the title input text box to see the pages settings.

Many of the settings are self explanatory, but the URL schema could probably use some explaining. For the category pages settings, the URL schema is category. This creates a category parameter. In fact, Symphony appends it to the default parameters created for each page. The URL schema category is only defined for the category page in the default template. This means that the parameter will only be available to this page. In the case of the category pages template, the URL schema allows the category page to display each category separately. If you wanted to create multiple page parameters taken from the URL, separate the parameter names with a / in the URL schema.

<xsl:template match="data">
    <div class="category">
        <h2>
            <xsl:call-template name="get-selected-category"/>
            <small class="button"><a href="{$root}/archive/">Organise by archive</a></small>
        </h2>

        <div class="other"><xsl:call-template name="get-subcategory-list"/></div>

        <xsl:choose>
            <xsl:when test="not(//category[@handle=$category]) and $category = not('') ">
                <p>There are no entries for this category.</p>
            </xsl:when>
            <xsl:when test="$category=''">
                <p>Please select a category.</p>
            </xsl:when>
            <xsl:otherwise>
                <ul class="results">
                    <xsl:apply-templates select="//category[$category=@handle]//entry"/>
                </ul>
            </xsl:otherwise>
        </xsl:choose>
    </div>
</xsl:template>

<xsl:template match="entry">
    <h3>
        <a href="{$root}/permalink/{@handle}/"><xsl:value-of select="title"/></a> by <xsl:value-of select="author"/>
    </h3>
    <p><xsl:value-of select="excerpt"/></p>
</xsl:template>

The first thing you’ll notice is that there are two template elements in this page, <xsl:template match="data"> and <xsl:template match="entry">, that will be called into action by the master template when a user visits the category page. You’ll also note the more advanced usage of <xsl:apply-templates> which ties the two templates together. The <xsl:apply-templates> mimics the <xsl:for-each> here and it will apply the second template more than once if a node-set is returned by the XPath expression in the select attribute.

I’m afraid our journey has come to an end. But don’t let that stop you from exploring!

Emerging from the bush

What… did you think we were going to hold hands? That’s not my kind of walkabout. Spend the time and investigate the other default pages on your own. Use the resources on the wiki. There are an abundance of XML, XPath, and XSLT tutorial web sites at your disposal. And remember, no one goes to the Symphony alone, don’t hesitate to post in the forums on Overture if you need help.

Once you gain the templating concepts, you’ll want to check out the articles on creating your own event and data source.

If there’s one thing I want you to leave with, having read this article, it would be that you cannot break that from which you can reinstall. Learn, break, and have fun with the default template before creating your own web site.

Mark Lewis http://overture21.com/forum/comments.php?DiscussionID=92