XML.com: XML From the Inside Out
oreilly.comSafari Bookshelf.Conferences.

advertisement

Template Languages in XSLT

March 27, 2002

Introduction

Despite its simplicity and its original purpose, XSLT is an extremely rich and powerful programming language. Just about anything that can be done with XML can be implemented in XSLT -- all it really takes is a little bit of creativity and a whole lot of pointy brackets.

One of the most common uses of XSLT is to transform XML content into something more suitable for viewing. This separation between content and presentation seems to be the most often cited advantage for many XML advocates. XSLT was designed specifically for this task

It could be argued, however, that, XSLT fails miserably at separating these two layers. Traversing source documents with any sort of XPath or XSLT instructions like xsl:for-each and xsl:apply-templates in your style sheets is like opening a connection to a database and performing a query in the middle of an ASP or JSP page. Good programmers don't do this because it breaks the separation between the presentation and data tiers in their applications.

Thinking about it from an altogether different perspective, having literal result elements interspersed with XSLT instructions in your transforms is like generating HTML by concatenating strings and then printing them to your output (as is often done when implementing servlets). Most designers can't work in an environment like that. Even if they can, they shouldn't have to concern themselves with all the logic of extracting and manipulating the data they're trying to present.

Table of Contents

Introduction

Literal Result Elements

Instructions

Simple Conditionals (if)

Loops (for-each)

Advanced Conditionals (choose/when/otherwise)

Instruction Parameters (attributes)

Attribute Value Templates

Conclusion

Bibliography

No matter how you look at, you've already lost the separation you've been trying so hard to retain. If your style sheets are coupled to the structure of your source documents, even slight modifications to your vocabulary could require updates to each and every style sheet that operates on those documents.

Eric van der Vlist introduced the concept of "Style-free XSLT Style Sheets" in November, 2000. That article served as the inspiration for implementing my own XSLT-like template language (in XSLT) designed specifically for transforming instances of a particular vocabulary into whatever output format a designer could dream up without requiring any knowledge of XPath, XSLT, or the XML vocabulary they were transforming. This language included all of the traditional control flow constructs necessary to generate the desired output.

This article will show you how to implement your own specialized template languages by building up a simple example capable of transforming a music database in XML into any form of HTML.

Example 1. A sample source document (collection.xml)
<collection>

        <owner>
                <name><given>Jason</given>
                <family>Diamond</family></name>
                (<email>jason@injektilo.org</email>)
        </owner>

        <album>
                <artist>Radiohead</artist>
                <title>OK Computer</title>
        </album>

        <album>
                <artist>Sigur R&#243;s</artist>
                <title>&#193;g&#230;tis Byrjun</title>
        </album>


        <album>
                <artist>Mogwai</artist>
                <title>Kicking a Dead Pig</title>
        </album>

</collection>

All of the files referenced in this article can be found in the associated archive. Included in that archive is a slightly more practical example of using the same template to process two different versions of RSS.

Literal Result Elements

Like XSLT, templates in our template language will be well-formed XML documents containing both literal result elements and instructions. Handling literal result elements is easy -- just copy them to the result tree.

Example 2. Our simple identity transform (transform1.xslt)

<xsl:transform version="1.0" 
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:param name="template-uri" />

<xsl:variable name="template" 
        select="document($template-uri)" />
<xsl:variable name="source" select="/" />

<xsl:template match="/">
        <xsl:apply-templates 
                select="$template/node()" />
</xsl:template>

<xsl:template match="*">
        <xsl:element name="{name()}">
                <xsl:apply-templates 
                        select="@* | node()" />
        </xsl:element>
</xsl:template>

<xsl:template match="@*">
        <xsl:attribute name="{name()}">
                <xsl:value-of select="." />
        </xsl:attribute>
</xsl:template>

<xsl:template match="text()">
        <xsl:if test="normalize-space()">
                <xsl:value-of select="." />
        </xsl:if>
</xsl:template>

</xsl:transform>

There's a couple of things to note about this example. First, this transform requires a parameter named template-uri. This URI is used as the input to the document function to retrieve the actual contents of our template. We start the transform off by processing the nodes in the template document and not the source document (although we do save the root of the source document in the source variable so that we can access it later).

Related Reading

XSLT

XSLT
By Doug Tidwell

With just a few small variations, the transform almost looks like the identity transform. We're using the xsl:element and xsl:attribute instructions instead of xsl:copy since xsl:copy automatically copies the namespace nodes of the current node which would include the template language namespace declaration. We're also only copying text nodes over when they don't consist of just whitespace, purely for aesthetic reasons.

In XSLT templates, literal result elements are the elements that do not belong to the XSLT namespace. Assuming the template language namespace name is http://xml.com/my-template-language namespace, the following template will produce an identical result document (minus the namespace declaration).

Example 3. A useless template (template1.xml)

<html xmlns:my="http://xml.com/my-template-language">
<body>
        <h1>My Collection</h1>
</body>
</html>

Our template language is, so far, worthless. That's about to change with the addition of our first instruction.

Pages: 1, 2, 3

Next Pagearrow