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?
- You won’t be creating plug-ins for your template.
- You can apply XSLT to applications and web design outside of Symphony because it’s a recommended web standard.
- You have an abundance of resources and documentation available to you on the web to learn XSLT.
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 provides structured data.
- XPath allows XSLT to navigate the XML data and pull out the pieces of information we want.
- XSLT will transform the data into our markup for the browser.
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.
- Category and name are both examples of an element. An element includes the content between the tags, as well as the tags themselves.
- Data is the root element, and the parent element to categories.
- Alternatively, categories is a child element of data.
- Entry is the parent element to time, title, author, excerpt, and comments.
- Alternatively, time, title, author, excerpt, and comments are a child elements of their parent element entry.
- An element can be both the parent element and a child element.
- An element can have several child elements but only one parent element.
- Category and entry elements both have an attribute named handle.
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.
nodenameselects all child nodes of the node./selects from the root node.//selects nodes that match the expression no matter where they are in the XML ..selects a current node...selects the parent of the current node.@selects attributes.*matches any element node.@*matches any attribute node.
Let’s take a look at some examples using the previous XML data source example and our newfound love of XPath syntax.
/data/categories/categorySelects the category element node.//categories/categorySelects the category element node.//category/*Selects any node that is a descendent of category.//nameSelects the name element, anywhere in the XML .//@handleSelects the handle attribute of both category and entry.category//nameSelects the name element if it is a descendent of category.
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.
=equal to!=not equal to<less than>greater than<=less than or equal to>=greater than or equal to
Let’s look at a few examples of predicates in action!
//entry[@handle = 'all-the-way-from-australia']Selects entry elements that have an attribute named handle that is equal to “all-the-way-from-Australia”.//entry[@handle]Selects all entries that have an attribute named handle. Note that this results in the same node selection as//entry@handle.//entry[@handle = 'all-the-way-from-australia']/comments[position() <= 3]Selects the first three comment elements of entry elements that have an attribute named handle that is equal to “all-the-way-from-Australia”.
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.
//entry[@handle and position() <= 2]Selects the first two entry elements that have an attribute named handle.
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.
- Pages contain page XSLT templates.
- Masters contain master XSLT templates.
- Utilities contain reusable XSLT templates which can be utilized by all pages and master templates.
- Assets contain CSS and Javascripts
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.
<xsl:apply-templates/>element is used in the default Symphony master template. Symphony applies the appropriate page template according to the URL, and accompanying XSLT templates in utilities.<xsl:apply-templates/>has two attributes for advanced users to be more selective in what templates are applied.<xsl:template>element has two important attributesnameandmatchwhich are used to determine if the template should be applied.<xsl:apply-templates/>utilizes thematchattribute of the<xsl:template>element to determine if the template should be applied. If thenameattribute is used and not thematchattribute, then the template is called by<xsl:call-template>. You will see ample usage of the latter method used in the default Symphony template.
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