XSL (eXtensible Stylesheet Language)

Sample XML Document

catalog.xml

<?xml version="1.0" encoding="ISO-8859-1"?>
<catalog>
  <cd country="UK">
    <title>Dark Side of the Moon</title>
    <artist>Pink Floyd</artist>
    <price>10.90</price>
  </cd>
  <cd country="UK">
    <title>Space Oddity</title>
    <artist>David Bowie</artist>
    <price>9.90</price>
  </cd>
  <cd country="USA">
    <title>Aretha: Lady Soul</title>
    <artist>Aretha Franklin</artist>
    <price>9.90</price>
  </cd>
</catalog>

Applying XSLT Stylesheets to XML Documents

drawing

There are three ways of applying an XSLT stylesheet to an XML document:

  1. Directly applying an XSLT processor to the XML document and the XSLT stylesheet; e.g. on command line (libxml2 tool shown here):

    $ xsltproc page1.xsl bib.xml
  2. Calling an XSLT processor from within a (Python or Java) program

    macbook-pro:xsl raj$ more xslTransform.py 
    import sys
    from lxml import etree
    
    def xslTransform(xsl,xml):
      xslt_root = etree.parse(xsl)
      transform = etree.XSLT(xslt_root)
      xml_root = etree.parse(xml)
      result = transform(xml_root)
      return result
    
    def main():
      print(xslTransform(sys.argv[1],sys.argv[2]))
    
    main()
    $ python3 xslTransform.py page1.xsl bib.xml
  3. Adding to the XML document a link to the XSL stylesheet and letting the browser do the transformation

    <?xml version="1.0"?>
    <?xml-stylesheet type="text/xsl" href="page1.xsl"?>
    
    <Journals>
      <Journal>
      ...
      ...
      </Journal>
    </Journals>

The Root of the XSL Document (program)

The root element of the XSL document (program) should be one of the following:

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

or

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

The xsl namespace allows the XSL processor to distinguish between XSL tags and tags of the result document

How Does XSLT Work?

Templates

A template has the form

<xsl:template match="pattern">
  ... Template content ...
</xsl:template>

The content of a template consists of

The pattern syntax is a subset of XPath

Simple Example

Hello World! (p1.xsl)

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

  <xsl:template match="/">
    <html>
    <body>
    <h1>Hello World</h1>
    </body>
    </html>
  </xsl:template>

</xsl:stylesheet>

Test this and subsequent examples on Python’s http server:

$ python3 -m http.server

XSL Processing

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

Example with xsl:apply-templates (p2.xsl)

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

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

  <xsl:template match="cd">
    <h2>A CD!</h2>
  </xsl:template>

</xsl:stylesheet>

Default Templates

<xsl:template match="/ | *">
  <xsl:apply-templates/>
</xsl:template>

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

Interaction of Default and User Defined Templates (p3.xsl)

<?xml version="1.0" encoding="ISO-8859-1"?>
<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:template match="cd[title='Space Oddity']">
    <h1>Hello World</h1>
  </xsl:template>

</xsl:stylesheet>

The Most Frequently Used Elements of XSL

<xsl:value-of select="xpath-expression"/>
<xsl:for-each select="xpath-expression"/>
<xsl:if test="xpath-expression"/>                  
<xsl:if test="xpath-expression=value"/>

The <xsl:value-of> Element

<xsl:value-of select="xpath-expression"/>

Example for value-of (p4.xsl)

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

  <xsl:template match="/">
    <html>
      <body>
        <h2>A CD Catalog</h2>
        <table border="1">
        <tr bgcolor="yellow">
        <th>Title</th>
        <th>Artist</th>
        </tr>
        <tr>
        <td><xsl:value-of select="catalog/cd/title"/></td>
        <td><xsl:value-of select="catalog/cd/artist"/></td>
        </tr>
        </table>
      </body>
    </html>
  </xsl:template>

</xsl:stylesheet>

Note that only the first matched element is retrieved for each <xsl:value of>

The <xsl:for-each> Element

<xsl:for-each select="xpath-expression"/>

Example for for-each (p5.xsl)

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

  <xsl:template match="/">
    <html>
      <body>
        <h2>A CD Catalog</h2>
        <table border="1">
        <tr bgcolor="yellow">
        <th>Title</th>
        <th>Artist</th>
        </tr>
        <xsl:for-each select="catalog/cd">
          <tr>
          <td><xsl:value-of select="title"/></td>
          <td><xsl:value-of select="artist"/></td>
          </tr>
        </xsl:for-each>
        </table>
      </body>
    </html>
  </xsl:template>

</xsl:stylesheet>

Note that if we change

<xsl:for-each select="catalog/cd">

to

<xsl:for-each select="catalog/cd[price &lt; 10]">

we will get only CDs which have a price less than 10.

Example for for-each (p6.xsl)

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

  <xsl:template match="/">
    <html>
      <body>
        <h2>A CD Catalog</h2>
        <table border="1">
        <tr bgcolor="yellow">
        <th>Title</th>
        <th>Artist</th>
        </tr>
        <xsl:for-each select="catalog/cd[price &lt; 10]">
          <tr>
          <td><xsl:value-of select="title"/></td>
          <td><xsl:value-of select="artist"/></td>
          </tr>
        </xsl:for-each>
        </table>
      </body>
    </html>
  </xsl:template>

</xsl:stylesheet>

The <xsl:sort> Element

Example for sort (p7.xsl)

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

  <xsl:template match="/">
    <html>
      <body>
        <h2>A CD Catalog</h2>
        <table border="1">
        <tr bgcolor="yellow">
        <th>Title</th>
        <th>Artist</th>
        </tr>
        <xsl:for-each select="catalog/cd">
        <xsl:sort select="artist"/>
          <tr>
          <td><xsl:value-of select="title"/></td>
          <td><xsl:value-of select="artist"/></td>
          </tr>
        </xsl:for-each>
        </table>
      </body>
    </html>
  </xsl:template>

</xsl:stylesheet>

The <xsl:if> Element

Example for if (p8.xsl)

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

  <xsl:template match="/">
    <html>
      <body>
        <h2>A CD Catalog</h2>
        <table border="1">
        <tr bgcolor="yellow">
        <th>Title</th>
        <th>Artist</th>
        </tr>
        <xsl:for-each select="catalog/cd">
          <xsl:if test="price &gt; 10">
            <tr>
            <td><xsl:value-of select="title"/></td>
            <td><xsl:value-of select="artist"/></td>
            </tr>
          </xsl:if>
        </xsl:for-each>
        </table>
      </body>
    </html>
  </xsl:template>

</xsl:stylesheet>

Applying Templates Recursively

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

  <xsl:template match="/">
    <html>
    <body>
    <h2>A CD Catalog</h2>
      <xsl:apply-templates/>
    </body>
    </html>
  </xsl:template>

  <xsl:template match="cd">
    <p>
    <xsl:apply-templates select="title"/>
    <xsl:apply-templates select="artist"/>
    </p>
  </xsl:template>

  <xsl:template match="title">
    Title: <span style="color:red">
    <xsl:value-of select="."/>
    </span>
    <br />
  </xsl:template>

  <xsl:template match="artist">
    Artist: <span style="color:green">
    <xsl:value-of select="."/>
    </span>
    <br />
  </xsl:template>

</xsl:stylesheet>

Is Recursive Application of Templates Really Needed?

Recursive Template Application

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

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

</xsl:stylesheet>

Summary