XSLT Guides
Common XSLT transformation patterns, each tagged with the version it needs so you know whether it'll run in the compiler's XSLT 1.0 engine or the XSLT 2.0/3.0 engine. Sample XML and the matching stylesheet sit side by side — paste both straight into the XSLT Compiler to try them.
1. XML to HTML Table
All VersionsTransform a list of XML elements into an HTML table.
<catalog>
<book>
<title>XML Toolkit</title>
<author>A. Novak</author>
</book>
<book>
<title>Data Pipelines</title>
<author>R. Singh</author>
</book>
</catalog>
<table>
<xsl:for-each select="catalog/book">
<tr>
<td><xsl:value-of select="title"/></td>
<td><xsl:value-of select="author"/></td>
</tr>
</xsl:for-each>
</table>
2. XML to Plain Text
All VersionsUse method="text" in <xsl:output> to extract plain text with no markup.
<catalog>
<book>
<title>XML Toolkit</title>
<author>A. Novak</author>
</book>
</catalog>
<xsl:output method="text"/>
<xsl:template match="/">
<xsl:for-each select="//book">
<xsl:value-of select="title"/> by <xsl:value-of select="author"/><xsl:text>
</xsl:text>
</xsl:for-each>
</xsl:template>
3. Filtering with xsl:if
All VersionsShow only books published after 1950.
<catalog>
<book>
<title>Old Classic</title>
<year>1932</year>
</book>
<book>
<title>Modern Read</title>
<year>1998</year>
</book>
</catalog>
<xsl:for-each select="catalog/book">
<xsl:if test="year > 1950">
<p><xsl:value-of select="title"/></p>
</xsl:if>
</xsl:for-each>
4. Sorting with xsl:sort
All VersionsSort books alphabetically by title before rendering.
<catalog>
<book><title>Zebra Facts</title></book>
<book><title>Apple Pie</title></book>
<book><title>Mango Tree</title></book>
</catalog>
<xsl:for-each select="catalog/book">
<xsl:sort select="title" order="ascending"/>
<p><xsl:value-of select="title"/></p>
</xsl:for-each>
5. Grouping with xsl:for-each-group
XSLT 2.0 XSLT 3.0
Group orders by customer and total each group. xsl:for-each-group was
introduced in XSLT 2.0, so this won't run on the compiler's 1.0 engine.
<orders>
<order customer="Acme">100</order>
<order customer="Acme">250</order>
<order customer="Globex">75</order>
</orders>
<xsl:for-each-group select="orders/order" group-by="@customer">
<p>
<xsl:value-of select="current-grouping-key()"/>:
<xsl:value-of select="sum(current-group())"/>
</p>
</xsl:for-each-group>
6. Pattern Matching with xsl:analyze-string
XSLT 2.0 XSLT 3.0
Reformat a phone number using a regular expression. xsl:analyze-string and
regex support arrived in XSLT 2.0.
<contact>
<phone>5551234567</phone>
</contact>
<xsl:analyze-string select="contact/phone" regex="(\d{3})(\d{3})(\d{4})">
<xsl:matching-substring>
(<xsl:value-of select="regex-group(1)"/>)
<xsl:value-of select="regex-group(2)"/>-<xsl:value-of select="regex-group(3)"/>
</xsl:matching-substring>
</xsl:analyze-string>
7. Custom Functions with xsl:function
XSLT 2.0 XSLT 3.0
Define a reusable function to compute a discounted price. User-defined functions
(xsl:function) need XSLT 2.0 or later and a namespace for the function name.
<item>
<price>100</price>
</item>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ex="http://example.com/fn">
<xsl:function name="ex:discount">
<xsl:param name="price"/>
<xsl:sequence select="$price * 0.9"/>
</xsl:function>
<xsl:template match="item">
<xsl:value-of select="ex:discount(price)"/>
</xsl:template>
</xsl:stylesheet>
8. Splitting Output with xsl:result-document
XSLT 2.0 XSLT 3.0
Write one output file per book instead of a single combined result.
xsl:result-document is a 2.0/3.0 feature for producing multiple outputs
from a single transformation.
<catalog>
<book id="bk101">
<title>XML Toolkit</title>
</book>
<book id="bk102">
<title>Data Pipelines</title>
</book>
</catalog>
<xsl:for-each select="catalog/book">
<xsl:result-document href="{@id}.xml">
<book><xsl:copy-of select="title"/></book>
</xsl:result-document>
</xsl:for-each>
9. JSON Output with xsl:map
XSLT 3.0
Produce JSON directly from XML using maps and xsl:output method="json" —
both are XSLT 3.0-only additions, so this needs the 3.0 engine specifically.
<person>
<name>Ada</name>
<age>32</age>
</person>
<xsl:output method="json"/>
<xsl:template match="/person">
<xsl:map>
<xsl:map-entry key="'name'" select="name"/>
<xsl:map-entry key="'age'" select="number(age)"/>
</xsl:map>
</xsl:template>