XSLT processing with xsltproc
(August 2004)

This article shows how to use XSLT style sheets to create HTML documents out of XML data files.
The processing is done with the xsltproc tool.
The XML file contains the data.
The XSLT file tells how the data is to be displayed.
One XSLT file may be used to process several XML files and generate as many HTML pages, with similar graphical presentation.
Table of contents

Let's start with a simple example

How is the processing done ?

A more complex example (HTML generation)

The name() function

The <xsl:copy> instruction

Including comments

Using the -stringparam option of xsltproc

For more information

Let's start with a simple example

data.xml
<?xml version="1.0"?>
<article>
  <title>The Pecan pie recipe</title>
  <ingredients>Eggs, Sugar, Pecan nuts</ingredients>
  <body>
Scramble the eggs, add the sugar and the pecan nuts.
Cook in the oven for 30 minutes.
  	<br/>
  </body>
</article>
	
transform.xsl
<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="article">

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

Ingredients:
------------
<xsl:value-of select="ingredients"/>

Procedure:
----------
<xsl:apply-templates select="body"/>

**********************************************
</xsl:template>
</xsl:stylesheet>
	
shell> xsltproc transform.xsl data.xml > output.txt
output.txt
<?xml version="1.0"?>

--- The Pecan pie recipe ---

Ingredients:
------------
Eggs, Sugar, Pecan nuts

Procedure:
----------

Scramble the eggs, add the sugar and the pecan nuts.
Cook in the oven for 30 minutes.
  
**********************************************
    

How is the processing done ?

The XSL file defines some rules that will be applied when needed. The order of the rules does not matter. A rule is defined by a <xsl:template match="..."> instruction.

The XML file is read sequentially.
For each XML part encountered, the XSLT processor looks for a dedicated rule in the XSL file, and applies this rule if one is found.

In our example, the XSLT processor encounters first the <article> tag and then applies the XSLT rule described in <xsl:template match="article"> on the <article>...</article> part.
After the processing of the whole <article>...</article> part, the XSLT processor continues with what follows (i.e. nothing in our example).

Inside the processing of an XML part, one can specify special processing for some other XML tag, with the <xsl:apply-templates select="..."/> instruction.

A more complex example (HTML generation)

data2.xml
<?xml version="1.0"?>
<main>

<article>
  <title>The Pecan pie recipe</title>
  <ingredients>Eggs, Sugar, Pecan nuts</ingredients>
  <body>
    Scramble the eggs, add the sugar and the pecan nuts.<br/>
    Cook in the oven for 30 minutes.<br/>

    (<a href="http://x.y.com/">click here</a>)
  </body>
</article>

<article>
  <title>The scramble eggs recipe</title>
  <ingredients>Eggs</ingredients>
  <body>
    Scramble the eggs.<br/>
    Cook in the pan for 4 minutes.<br/>
  </body>
</article>
</main> 
transform2.xsl
<?xml version="1.0" encoding="ISO-8859-15"?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output encoding="ISO-8859-15"/>

<xsl:template match="br">
  <br/>
</xsl:template>

<xsl:template match="a">
  <a href="{@href}"><xsl:apply-templates/></a>
</xsl:template>

<xsl:template match="article">
<h3><xsl:value-of select="title"/></h3>
<u>Ingredients:</u> <xsl:value-of select="ingredients"/>
<br/>
<u>Procedure:</u> <xsl:apply-templates select="body"/>
</xsl:template>

<xsl:template match="main">
  <html>
  <head>
  <title>recipes</title>
  </head>
  <body bgcolor="#ffffff">
  <h2>Our best recipes "à la française"</h2>
  <xsl:apply-templates select="article"/>
  </body>
  </html>
</xsl:template>
</xsl:stylesheet>
    
shell> xsltproc transform2.xsl data2.xml > output.html
output.html
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-15">
<title>recipes</title>
</head>
<body bgcolor="#ffffff">
<h2>Our best recipes "à la française"</h2>
<h3>The Pecan pie recipe</h3>
<u>Ingredients:</u>Eggs, Sugar, Pecan nuts<br><u>Procedure:</u>
    Scramble the eggs, add the sugar and the pecan nuts.<br>
    Cook in the oven for 30 minutes.<br>

    (<a href="http://x.y.com/">click here</a>)
  <h3>The scramble eggs recipe</h3>
<u>Ingredients:</u>Eggs<br><u>Procedure:</u>
    Scramble the eggs.<br>
    Cook in the pan for 4 minutes.<br>
  <body><html>

    

Notes about this example:

The name() function

Using <xsl:element name="{name()}"> to quote HTML tags:
excerpt of data3.xml
<h2>TITLE OF THE PARAGRAPH</h2>
<u>notes:</u>
one<br/>
two<br/>
  
excerpt of transform3.xsl
<xsl:template match="ul|li|b|u|i">
  <xsl:element name="{name()}">
        <xsl:apply-templates/>
  </xsl:element>
</xsl:template>

<xsl:template match="br">
  <xsl:element name="{name()}"/>
</xsl:template>
shell> xsltproc transform3.xsl data3.xml > output3.html
excerpt of output3.html
TITLE OF THE PARAGRAPH
<u>notes:</u>
one<br/>
two<br/>
  

The <h2>...</h2> tags have been removed becaused they are not handled by the XSL file.

The <xsl:copy> instruction

This let the processing simply copy the input tags without any transformation:
excerpt of data.xml
<any_tag value="322"/>

<another_tag>
  Mister Rabbit goes to the swimming pool.
</another_tag>
    
excerpt of transform.xsl
<xsl:template match="@*|node()">
  <xsl:copy>
    <xsl:apply-templates/>
  </xsl:copy>
</xsl:template>
    
shell> xsltproc transform.xsl data.xml > output.html
excerpt of output.html
<any_tag/>

<another_tag>
  Mister Rabbit goes to the swimming pool.
</another_tag>
    

Including comments

excerpt of data.xml
...
    
excerpt of transform.xsl
<xsl:comment>This file is automatically generated. Do not edit! </xsl:comment>
    
shell> xsltproc transform.xsl data.xml > output.html
excerpt of output.html
<!--This file is automatically generated. Do not edit! -->
    

Using the -stringparam option of xsltproc

excerpt of data.xml
...
    
transform.xsl
<input type="hidden" name="date" value="{$date}"/>
    
shell> xsltproc -stringparam date "2005-01-31" transform.xsl data.xml > output.html
excerpt of output.html
<input type="hidden" name="date" value="2005-01-31"/>
    

This does not work if {$date} is not used inside a tag <x ... y="{$date}" ...>.

For more information

XSLT processing is not limited to HTML generation and can be used for any data processing.
Here are other ressources on Internet: