Fork me on GitHub

Project Notes

#431 XSLT

About Extensible Stylesheet Language Transformations (XSLT), with a simple example on macOS. Also a discussion of the current state of support and the pending removal of XSLT support from browsers.

Notes

XSLT (Extensible Stylesheet Language Transformations) is a language originally designed for transforming XML documents into other XML documents, or other formats such as HTML or plain text.

XSLT has been particularly supported over the years by “back-end” technology players such as Microsoft, IBM, Oracle, and the Apache Software Foundation.

XSLT lost its prominence around 2008 with APIs moving towards JSON, and the rise of application-Language templating (Rails, Django, Handlebars), and browser support stagnated.

XSLT has been back in the news recently, as XSLT support is being removed from browsers - see the reporting in Security Now 1051 for example.

Google Chrome - Removing XSLT for a more secure browser has already been announced, with many expecting Safari/WebKit and Mozilla/Firefox to follow. There has been significant push-back however, as many government and legal applications reply on browser-based XSLT support.

XSLT In a Nutshell

  • XSLT (Extensible Stylesheet Language Transformations) is a declarative language for transforming XML documents into other formats (XML, HTML, or text).
  • Works by applying templates to nodes in an XML document.
  • Uses pattern matching + tree transformation rather than procedural steps.
  • Navigation and selection are done using XPath.
  • Standardized by the World Wide Web Consortium.
    • XSLT 1.0 (1999): first recommendation, widely supported, basic transformations
    • XSLT 2.0: sequences, regex, stronger typing
    • Current Version: XSLT 3.0 (2017): streaming, functions, packages
  • Core Processing Model: XML tree → match templates → build result tree
  • XSLT processors include implementations such as Saxon and Xalan.

Minimal Stylesheet

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

<xsl:template match="/">
  <html>
    <body>
      <xsl:apply-templates/>
    </body>
  </html>
</xsl:template>

</xsl:stylesheet>

Core Elements

Template

Defines how nodes should be transformed.

<xsl:template match="book">
  <p><xsl:value-of select="title"/></p>
</xsl:template>

Apply Templates

Processes child nodes.

<xsl:apply-templates select="book"/>

Value Output

Outputs text value.

<xsl:value-of select="title"/>

Loop

<xsl:for-each select="catalog/book">
  <li><xsl:value-of select="title"/></li>
</xsl:for-each>

Conditional

<xsl:if test="price &gt; 20">
  <expensive/>
</xsl:if>

Choose / Case

<xsl:choose>
  <xsl:when test="price &lt; 10">cheap</xsl:when>
  <xsl:otherwise>normal</xsl:otherwise>
</xsl:choose>

Variables

<xsl:variable name="tax" select="0.2"/>

Immutable once set.

Parameters (External Input)

<xsl:param name="currency"/>

XPath Basics

Common selectors used inside XSLT:

Expression Meaning
/ root
book child elements
//book anywhere in document
@id attribute
book/title child path
book[price>10] filtered nodes

Examples:

book[1]
book[@category='fiction']
sum(book/price)

Sorting

<xsl:apply-templates select="book">
  <xsl:sort select="title"/>
</xsl:apply-templates>

Creating Elements

<xsl:element name="item">
  <xsl:value-of select="title"/>
</xsl:element>

Or literal result:

<li><xsl:value-of select="title"/></li>

Attribute Creation

<xsl:attribute name="class">highlight</xsl:attribute>

Output Control

<xsl:output method="html" indent="yes"/>

Methods:

  • xml
  • html
  • text

Template Matching Patterns

Pattern Matches
/ document root
* any element
book book elements
@* any attribute
text() text nodes

Example:

<xsl:template match="text()"/>

(suppresses raw text)

Example: HTML Book Catalog Generation

This is a simple example of transforming an XML catalog of book records into HTML.

The source records are in books.xml:

<?xml version="1.0" encoding="UTF-8"?>
<catalog>
  <book isbn="9798707512940">
    <title>Diary of a War Crime</title>
    <author>Simon McCleave</author>
  </book>
  <book isbn="9780063250864">
    <title>Yellowface</title>
    <author>R.F. Kuang</author>
  </book>
</catalog>

The transformation is defined in books-to-html.xslt:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:output method="html" indent="yes"/>

<xsl:template match="/">
  <html>
    <body>
      <h2>Book Catalog</h2>
      <ul>
        <xsl:apply-templates mode="toc"/>
      </ul>
      <hr/>
        <xsl:apply-templates select="catalog/book"/>
    </body>
  </html>
</xsl:template>

<xsl:template match="book" mode="toc">
  <li>
    <a href="#{generate-id()}"><xsl:value-of select="title"/></a><br/>
  </li>
</xsl:template>

<xsl:template match="book">
  <h3 id="{generate-id()}"><xsl:value-of select="title"/></h3>
  <p>
  Author: <xsl:value-of select="author"/>
  <br/>
  ISBN: <xsl:value-of select="@isbn"/>
  </p>
</xsl:template>

</xsl:stylesheet>

I am running this on macOS, and using xsltproc, which is installed by default as part of the libxslt. I use this to perform the transformation:

xsltproc books-to-html.xslt books.xml > books.html

The result is captured in books.html:

<html><body>
<h2>Book Catalog</h2>
<ul>
  <li>
<a href="#id1">Diary of a War Crime</a><br>
</li>
  <li>
<a href="#id2">Yellowface</a><br>
</li>
</ul>
<hr>
<h3 id="id1">Diary of a War Crime</h3>
<p>
  Author: Simon McCleave<br>
  ISBN: 9798707512940</p>
<h3 id="id2">Yellowface</h3>
<p>
  Author: R.F. Kuang<br>
  ISBN: 9780063250864</p>
</body></html>

Credits and References

About LCK#431
formatsXSLT

This page is a web-friendly rendering of my project notes shared in the LittleCodingKata GitHub repository.

Project Source on GitHub Return to the LittleCodingKata Catalog
About LittleCodingKata

LittleCodingKata is my collection of programming exercises, research and code toys broadly spanning things that relate to programming and software development (languages, frameworks and tools).

These range from the trivial to the complex and serious. Many are inspired by existing work and I'll note credits and references where applicable. The focus is quite scattered, as I variously work on things new and important in the moment, or go back to revisit things from the past.

This is primarily a personal collection for my own edification and learning, but anyone who stumbles by is welcome to borrow, steal or reference the work here. And if you spot errors or issues I'd really appreciate some feedback - create an issue, send me an email or even send a pull-request.

Follow the Blog follow projects and notes as they are published in your favourite feed reader