At Viewbook we are using XSLT (Extensible Stylesheet Language Transformations) to build a new generation of powerful website building tools within the Viewbook framework (more on that later). I have been working with XSLT for about 4 years now, so it came naturally to me to offer it as the preferred approach to get the system working. But using XSLT isn’t exactly a mainstream approach for web development (yet), so why did we choose XSLT for the job?
What does XSLT solve?
Thinking about how we would ideally set up the new range of tools, it quickly came down to one rather fundamental question. How can we easily combine a multitude of configuration and data sources into all the needed output types? And more importantly, how could we keep the overall system agile and scalable?
The configuration method of choice came down to XML (doesn’t it almost always). It’s easy to produce, great for rapid prototyping (just edit a static file) and can be easily generated by any back-end system. XML configuration does however has it downsides when you want to use it to generate the output. It’s pretty verbose and parsing can be a pain and can require a lot of code, and this is exactly where XSLT comes in.
What is XSLT?
So what is XSLT? In short it is a great way to loop through each and every bit of an XML source, and transform that bit into something else on the fly and only if needed. You can use it to generate any type of output from a single XML source: Text, XML, HTML, CSS, Javascript, SVG, a PDF or anything in between. In essence this means with XSLT you can produce any type of content and truly abstract your data and configuration from your output and transforming logic.
What does XSLT look like?
Letís do a concrete example. Suppose you want to render various pieces of HTML into one or more pages, where each bit has the same basic structure but different content and styling. And as a bonus letís keep the database as a flat as possible.
The XML configuration could look something like this:
-
<data>
-
-
<item>
-
-
<structure>
-
-
<section>
-
-
<header>
-
-
<h1 id="h-h1"/>
-
-
<p id="h-p"/>
-
-
</header>
-
-
<p id="s-p"/>
-
-
</section>
-
-
</structure>
-
-
<options>
-
-
<item type="content" id="h-h1">
-
Custom Title
-
</item>
-
-
<item type="content" id="h-p">
-
Lorem ipsum dolor sit amet, consecteturadipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore
-
-
magna aliqua.
-
</item>
-
-
<item type="content" id="s-p">
-
Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem
-
-
aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo.
-
-
</item>
-
-
<item type="style" id="h-h1">
-
font-size:24px
-
</item>
-
-
<item type="style" id="h-p">
-
font-size:14px
-
</item>
-
-
<item type="style" id="s-p">
-
font-size:12px
-
</item>
-
-
</options>
-
-
</item>
-
</data>
And with XSLT like this:
-
<!– load in your data –>
-
<xsl:variable name="data" select="document('http://url-to-your-data.xml')" />
-
-
<xsl:template match="/">
-
-
<!– loop through the basic structure –>
-
<xsl:apply-templates select="$data/data/item/structure/*" mode="html" />
-
-
<style>
-
-
<xsl:comment>
-
<!– sum up all css styles –>
-
<xsl:apply-templates select="$data/data/item/options/item[@type= 'style']" mode="style" />
-
</xsl:comment>
-
-
</style>
-
</xsl:template>
-
-
<!–
-
template copy using the "The Ninja Technique"
-
http://symphony-cms.com/learn/articles/view/html-ninja-technique/
-
–>
-
<xsl:template match="*" mode="html">
-
-
<!– store the content reference id –>
-
<xsl:variable name="el-id" select="@id" />
-
-
<xsl:element name="{name()}">
-
<xsl:choose>
-
<!–
-
This matches the elements 'id' from the config structure
-
with any possible 'id' in the config options and pasts in the content
-
–>
-
-
<xsl:when test="$el-id and $data/data/item/options/item[@type = 'content' and @id = $el-id]">
-
<xsl:apply-templates select="@*" mode="html" />
-
<xsl:value-of select="$data/data/item/options/item[@id = $el-id]" />
-
</xsl:when>
-
<xsl:otherwise>
-
<!– otherwise just copy the config structure –>
-
<xsl:apply-templates select="* | @* | text()" mode="html" />
-
</xsl:otherwise>
-
</xsl:choose>
-
</xsl:element>
-
</xsl:template>
-
-
<xsl:template match="@*" mode="html">
-
<xsl:attribute name="{name()}">
-
<xsl:value-of select="." />
-
</xsl:attribute>
-
</xsl:template>
-
<!– Template copy –>
-
-
-
<!– css style generation –>
-
<xsl:template match="item" mode="style">
-
<xsl:text>#</xsl:text>
-
<xsl:value-of select="@id" />
-
<xsl:text>{</xsl:text>
-
<xsl:value-of select="." />
-
<xsl:text>;}</xsl:text>
-
</xsl:template>
-
<!– css style generation –>
You would produce:
-
<section>
-
-
<header>
-
-
<h1 id="h-h1">
-
Custom Title
-
</h1>
-
-
<p id="h-p">
-
Lorem ipsum dolor sit amet, consecteturadipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
-
</p>
-
-
</header>
-
-
<p id="s-p">
-
Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa
-
-
quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo.
-
-
</p>
-
-
</section>
-
-
<style>
-
<!–#h-h1{font-size:24px;}#h-p{font-size:14px;}#s-p{font-size:12px;}–>
-
</style>
Obviously this is a pretty simple example witch could be improved upon, but thatís simply a case of making more specific template matches and adjust your XSLT as needed.
No disadvantages?
XSLT does has it’s downsides of course, like most technologies do. First of all mastering XSLT can be a steep learning curve and requires a different ‘mindset’ to get started. XSLT is a templating language, you loop, match and transform. Whereas other transform languages often use a loaded DOM and ‘paste’ new content in afterwards. The latter generally would be a more familiar approach for most developers.
Secondly XSLT isn’t really known for it’s mathematical prowess, it’s a XML transformation language after all. Although XSLT 2.0 does solve this for a great deal, that version isn’t really widespread yet. External libraries like EXSLT do solve much of the headaches in the mean time though. And finally working with very large XML documents (as in thousands of lines of XML) can pose performance issues if not careful, although I myself never run into this before.
Conclusion
So XSLT is a great way to produce any type of content from your database and really abstracts configuration from output. Besides this XSLT is a platform neutral way of rendering the output. So that means there is always a XSLT processor you can use in the language you’re most familiar with. And of course XSLT is just about transforming XML, nothing more and nothing less. So if you’re working with XML, XSLT is the way to go.