XSLT Explained — Transform XML into HTML & More
XSLT (eXtensible Stylesheet Language Transformations) is a language for transforming XML documents into other formats — most commonly HTML for web display, but also other XML structures, plain text, or even PDF — using template rules that match patterns in the source document.
What You’ll Learn
- How XSLT templates work with match patterns
- Using
xsl:for-eachto iterate over nodes - Using
xsl:value-ofto extract content - Transforming XML into a complete HTML page
Why XSLT Matters
XSLT separates data from presentation. You can have one XML file containing your data and multiple XSLT stylesheets to display it as a web page, a PDF, a mobile app view, or a plain-text report — without changing the data. This separation of concerns is why XSLT is used in publishing, e-commerce, and enterprise integration.
Doda Browser uses XSLT-like template patterns for rendering XML-based configuration as user-friendly pages. Durga Antivirus Pro uses XSLT to generate HTML threat reports from XML-formatted scan results.
Learning Path
flowchart LR
A[XML Basics] --> B[XPath Queries]
B --> C[XSLT Transformations<br/>You are here]
C --> D[XML Schema XSD]
D --> E[SOAP & WSDL]
Our Source XML
<?xml version="1.0" encoding="UTF-8"?>
<library>
<book category="fiction" id="b1">
<title>The Hobbit</title>
<author>J.R.R. Tolkien</author>
<year>1937</year>
<price currency="USD">12.99</price>
</book>
<book category="non-fiction" id="b2">
<title>A Brief History of Time</title>
<author>Stephen Hawking</author>
<year>1988</year>
<price currency="GBP">9.99</price>
</book>
<book category="fiction" id="b3">
<title>1984</title>
<author>George Orwell</author>
<year>1949</year>
<price currency="USD">10.99</price>
</book>
</library>How XSLT Works
Think of XSLT as a set of recipes for transforming your XML. Each recipe (template) says:
- “When you see THIS pattern in the XML…”
- “…replace it with THAT output.”
Basic XSLT Structure
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<!-- What to output when we start at the root -->
</xsl:template>
</xsl:stylesheet>Every XSLT file:
- Has a
<xsl:stylesheet>or<xsl:transform>root element - Declares the XSLT namespace:
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" - Contains one or more
<xsl:template>elements - Each template has a
matchattribute that selects which nodes it handles
Transforming XML to HTML
Let’s build a complete XSLT that transforms our library XML into an HTML page:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!-- Start at the root -->
<xsl:template match="/">
<html>
<head>
<title>Library Catalog</title>
<style>
body { font-family: Arial; margin: 20px; }
table { border-collapse: collapse; width: 100%; }
th, td { border: 1px solid #ccc; padding: 8px; }
th { background-color: #f0f0f0; }
</style>
</head>
<body>
<h1>Library Catalog</h1>
<table>
<tr>
<th>Title</th>
<th>Author</th>
<th>Year</th>
<th>Price</th>
</tr>
<xsl:apply-templates select="library/book"/>
</table>
</body>
</html>
</xsl:template>
<!-- Template for each book -->
<xsl:template match="book">
<tr>
<td><xsl:value-of select="title"/></td>
<td><xsl:value-of select="author"/></td>
<td><xsl:value-of select="year"/></td>
<td><xsl:value-of select="concat(price, ' ', price/@currency)"/></td>
</tr>
</xsl:template>
</xsl:stylesheet>How This Works
<xsl:template match="/">: This template matches the root node (/). It produces the HTML<html>,<head>, and<body>structure.<xsl:apply-templates select="library/book"/>: This is the engine of XSLT. It says: “For every book element inside library, find a matching template and run it.” It’s like a function call.<xsl:template match="book">: This template matches each<book>element. For each book, it creates an HTML table row.<xsl:value-of select="title"/>: Extracts the text content of the<title>child element and inserts it into the output.concat(price, ' ', price/@currency): Uses XSLT’sconcat()function to combine the price value, a space, and the currency attribute.
Expected HTML Output
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Library Catalog</title>
<style>
body { font-family: Arial; margin: 20px; }
table { border-collapse: collapse; width: 100%; }
th, td { border: 1px solid #ccc; padding: 8px; }
th { background-color: #f0f0f0; }
</style>
</head>
<body>
<h1>Library Catalog</h1>
<table>
<tr>
<th>Title</th>
<th>Author</th>
<th>Year</th>
<th>Price</th>
</tr>
<tr>
<td>The Hobbit</td>
<td>J.R.R. Tolkien</td>
<td>1937</td>
<td>12.99 USD</td>
</tr>
<tr>
<td>A Brief History of Time</td>
<td>Stephen Hawking</td>
<td>1988</td>
<td>9.99 GBP</td>
</tr>
<tr>
<td>1984</td>
<td>George Orwell</td>
<td>1949</td>
<td>10.99 USD</td>
</tr>
</table>
</body>
</html>xsl:for-each Loop
Sometimes it’s easier to use a loop rather than separate templates:
<xsl:template match="/">
<html>
<body>
<h1>Books by Category</h1>
<!-- Process fiction books -->
<h2>Fiction</h2>
<ul>
<xsl:for-each select="library/book[@category='fiction']">
<li>
<xsl:value-of select="title"/>
(<xsl:value-of select="year"/>)
</li>
</xsl:for-each>
</ul>
<!-- Process non-fiction books -->
<h2>Non-Fiction</h2>
<ul>
<xsl:for-each select="library/book[@category='non-fiction']">
<li>
<xsl:value-of select="title"/>
(<xsl:value-of select="year"/>)
</li>
</xsl:for-each>
</ul>
</body>
</html>
</xsl:template>Expected output:
<html>
<body>
<h1>Books by Category</h1>
<h2>Fiction</h2>
<ul>
<li>The Hobbit (1937)</li>
<li>1984 (1949)</li>
</ul>
<h2>Non-Fiction</h2>
<ul>
<li>A Brief History of Time (1988)</li>
</ul>
</body>
</html>Sorting with xsl:sort
Add sorting to your output:
<xsl:template match="/">
<html>
<body>
<h1>Books Sorted by Year</h1>
<ol>
<xsl:for-each select="library/book">
<xsl:sort select="year" data-type="number"/>
<li>
<xsl:value-of select="title"/>
(<xsl:value-of select="year"/>)
</li>
</xsl:for-each>
</ol>
</body>
</html>
</xsl:template>Expected output:
<html>
<body>
<h1>Books Sorted by Year</h1>
<ol>
<li>The Hobbit (1937)</li>
<li>1984 (1949)</li>
<li>A Brief History of Time (1988)</li>
</ol>
</body>
</html>Conditional Logic
XSLT supports xsl:if and xsl:choose for conditions:
<xsl:template match="book">
<tr>
<td><xsl:value-of select="title"/></td>
<td><xsl:value-of select="author"/></td>
<td>
<!-- Highlight old books -->
<xsl:choose>
<xsl:when test="year < 1950">
<span style="color:red;">
<xsl:value-of select="year"/> (Classic)
</span>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="year"/>
</xsl:otherwise>
</xsl:choose>
</td>
</tr>
</xsl:template>Real-World Use: RSS to HTML
Here’s a practical use — transforming an RSS feed into a readable HTML page:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<h1><xsl:value-of select="rss/channel/title"/></h1>
<p><xsl:value-of select="rss/channel/description"/></p>
<xsl:for-each select="rss/channel/item">
<div style="margin-bottom: 20px;">
<h2><a href="{link}"><xsl:value-of select="title"/></a></h2>
<p><xsl:value-of select="description"/></p>
<small><xsl:value-of select="pubDate"/></small>
</div>
</xsl:for-each>
</body>
</html>
</xsl:template>
</xsl:stylesheet>Note the {link} syntax inside href — that’s an Attribute Value Template (AVT). The curly braces tell XSLT to evaluate the expression inside and use the result as the attribute value.
Security Angle
XSLT transformations can be a security risk when processing untrusted XML or XSLT files:
- XSLT Injection: If an attacker controls the XSLT, they can read files or perform server-side requests
- Denial of Service: Complex transformations can consume excessive CPU/memory
- Information Disclosure: Error messages may leak internal file paths
Durga Antivirus Pro always sanitizes XSLT files before processing and runs transformations in sandboxed environments with restricted file access.
Common Mistakes
1. Forgetting the XSLT namespace
<xsl:stylesheet version="1.0">
<!-- Missing xmlns:xsl declaration — will cause errors -->Always include xmlns:xsl="http://www.w3.org/1999/XSL/Transform".
2. Confusing xsl:apply-templates with xsl:call-template
xsl:apply-templates processes nodes based on their match patterns. xsl:call-template calls a named template directly by name.
3. Not escaping < in conditions
<xsl:if test="year < 1950"> <!-- WRONG: < is XML special char -->
<xsl:if test="year < 1950"> <!-- CORRECT -->4. Using xsl:value-of on an element with children
xsl:value-of only returns the text content. To include child elements in the output, use xsl:apply-templates or xsl:copy-of.
5. Forgetting that XSLT is case-sensitive
xsl:template works, xsl:Template doesn’t. All XSLT element names are lowercase.
Practice Questions
What does
xsl:apply-templatesdo? Processes child nodes by finding matching templates. It’s the main dispatch mechanism in XSLT.How do you extract text from an element in XSLT?
<xsl:value-of select="elementName"/>.What is the difference between
xsl:for-eachandxsl:apply-templates?xsl:for-eachiterates over nodes inline.xsl:apply-templatesdelegates processing to matching templates.How do you sort output in XSLT? Use
<xsl:sort select="field" order="ascending"/>insidexsl:for-eachorxsl:apply-templates.What does
concat()do in XSLT? Joins multiple strings together:concat('$', price)produces “$12.99”.
Challenge: Write an XSLT stylesheet that transforms XML employee data into an HTML page with a table sorted by salary (descending), with conditional formatting that highlights salaries above $100,000 in green and below $50,000 in red.
FAQ
Try It Yourself
Apply an XSLT transformation using the command line:
# Transform library.xml using library.xsl into HTML
xsltproc library.xsl library.xml > library.html
# View the result
cat library.htmlOr use Python's lxml library:
from lxml import etree
xml = etree.parse("library.xml")
xslt = etree.parse("library.xsl")
transform = etree.XSLT(xslt)
result = transform(xml)
print(str(result))Save the XML and XSLT from this tutorial, run the command, and open library.html in your browser to see the result.
What’s Next
| Tutorial | What You’ll Learn |
|---|---|
| XML Schema (XSD) Explained — Beginner’s Guide | Validate XML structure with schemas |
| XPath Explained — Querying XML | The query language used inside XSLT |
| XML Basics — Complete Guide | Foundational XML concepts |
Built by the developers of Doda Browser, DodaZIP, and Durga Antivirus Pro. Updated 2026-06-06.
What’s Next
Congratulations on completing this Xslt tutorial! Here’s where to go from here:
- Practice daily — Consistency is more important than long study sessions
- Build a project — Apply what you learned by building something real
- Explore related topics — Check out other tutorials in the same category
- Join the community — Discuss with other learners and share your progress
Remember: every expert was once a beginner. Keep coding!
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro