XML Tutorial · XPath, XSLT and XQuery · Lesson 14 of 28

XSLT Basics

Transforming XML with XSLT 1.0: templates, xsl:value-of, xsl:for-each, xsl:if, xsl:sort, and running a stylesheet from code.

Create a free account to save this page, take notes and track your progress. Sign in

What XSLT does

XSLT turns one XML document into another document: different XML, HTML or plain text. A stylesheet is a set of templates: "when you meet a node matching this pattern, output this".

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="text"/>
  <xsl:template match="/shop">
    <xsl:for-each select="product[stock > 0]">
      <xsl:sort select="price" data-type="number" order="descending"/>
      <xsl:value-of select="name"/>: <xsl:value-of select="format-number(price, '0.00')"/>
      <xsl:text>&#10;</xsl:text>
    </xsl:for-each>
  </xsl:template>
</xsl:stylesheet>
Instruction Does
xsl:template match="…" a rule for matching nodes
xsl:apply-templates select="…" process these nodes with their matching templates
xsl:value-of select="…" output the string value of an XPath
xsl:for-each / xsl:sort loop, optionally sorted
xsl:if test="…" / xsl:choose conditions
xsl:attribute, xsl:element, {…} in attributes build output nodes

Running a stylesheet

XSLT 1.0 is built into lxml (libxslt), the JDK (javax.xml.transform) and browsers (XSLTProcessor, see XML in JavaScript). PHP needs the xsl extension, which the in-browser PHP here doesn't include.

Price list with XSLTTry it yourself
from lxml import etree

shop = etree.fromstring(b"""<shop>
  <product sku="TEA-01" category="drinks"><name>Green tea</name><price>3.50</price><stock>40</stock></product>
  <product sku="COF-02" category="drinks"><name>Coffee beans</name><price>9.90</price><stock>0</stock></product>
  <product sku="MUG-07" category="kitchen"><name>Camel mug</name><price>12.00</price><stock>15</stock></product>
  <product sku="PAN-03" category="kitchen"><name>Frying pan</name><price>29.00</price><stock>4</stock></product>
</shop>""")
xslt = etree.XSLT(etree.fromstring(b"""
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="text"/>
  <xsl:template match="/shop">
    <xsl:for-each select="product[stock &gt; 0]">
      <xsl:sort select="price" data-type="number" order="descending"/>
      <xsl:value-of select="name"/>: <xsl:value-of select="format-number(price, '0.00')"/>
      <xsl:text>&#10;</xsl:text>
    </xsl:for-each>
  </xsl:template>
</xsl:stylesheet>"""))
print(str(xslt(shop)), end="")

Output

Frying pan: 29.00
Camel mug: 12.00
Green tea: 3.50

Whitespace-only text in a stylesheet is ignored, so <xsl:text> is how you output exact spaces and new lines.

XML to HTML

Templates and xsl:apply-templates are the idiomatic style: each template handles one kind of node.

Templates to HTMLTry it yourself
from lxml import etree

shop = etree.fromstring(b"""<shop>
  <product sku="TEA-01" category="drinks"><name>Green tea</name><price>3.50</price><stock>40</stock></product>
  <product sku="COF-02" category="drinks"><name>Coffee beans</name><price>9.90</price><stock>0</stock></product>
  <product sku="MUG-07" category="kitchen"><name>Camel mug</name><price>12.00</price><stock>15</stock></product>
  <product sku="PAN-03" category="kitchen"><name>Frying pan</name><price>29.00</price><stock>4</stock></product>
</shop>""")
to_html = etree.XSLT(etree.fromstring(b"""
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="html" indent="yes"/>
  <xsl:template match="/shop">
    <table>
      <tr><th>Product</th><th>Price</th></tr>
      <xsl:apply-templates select="product"/>
    </table>
  </xsl:template>
  <xsl:template match="product">
    <tr class="{@category}">
      <td><xsl:value-of select="name"/></td>
      <td><xsl:value-of select="price"/></td>
    </tr>
  </xsl:template>
  <xsl:template match="product[stock = 0]">
    <tr class="sold-out"><td colspan="2"><xsl:value-of select="name"/> (sold out)</td></tr>
  </xsl:template>
</xsl:stylesheet>"""))
print(str(to_html(shop)))

Output

<table>
<tr>
<th>Product</th>
<th>Price</th>
</tr>
<tr class="drinks">
<td>Green tea</td>
<td>3.50</td>
</tr>
<tr class="sold-out"><td colspan="2">Coffee beans (sold out)</td></tr>
<tr class="kitchen">
<td>Camel mug</td>
<td>12.00</td>
</tr>
<tr class="kitchen">
<td>Frying pan</td>
<td>29.00</td>
</tr>
</table>

Test yourself

Which XSLT instruction processes the selected nodes with their matching templates?

  1. xsl:apply-templates
  2. xsl:value-of
  3. xsl:copy-of
  4. xsl:call-template
Show answer

Answer: xsl:apply-templates

apply-templates hands each selected node to the best-matching template.

Was this page helpful?