XSLT Processing Model — Step-by-Step Transformation Guide
In this tutorial, you'll learn about XSLT Processing Model. We cover key concepts, practical examples, and best practices.
The XSLT processing model transforms XML documents using template rules that match nodes in the source tree, producing a result tree through recursive pattern matching rather than sequential instructions.
What You'll Learn
- How the XSLT processor navigates the source tree
- Template rules, match patterns, and the apply-templates mechanism
- Processing modes, built-in templates, and conflict resolution
- Controlling output order with sort and priority
Why the XSLT Processing Model Matters
Unlike procedural languages where you write step-by-step instructions, XSLT is declarative: you define templates that match nodes, and the processor decides when to invoke them. Understanding this model is essential for writing predictable transformations. Doda Browser uses XSLT internally to transform XML-based browser bookmarks into HTML for the bookmarks manager.
Learning Path
flowchart LR A[XPath Queries] --> B[XSLT Basics] B --> C[XSLT Processing Model
You are here] C --> D[XSLT Advanced] D --> E[XML Schema XSD]
How the XSLT Processor Works
The processor starts at the source root and follows this cycle:
- Build source tree — Parse the XML into a node tree
- Load stylesheet — Parse the XSLT into template rules
- Process root — Find a matching template for the root node
- Process children — Apply templates to child nodes recursively
- Output result — Serialize the result tree
flowchart TD
A[XML Source] --> B[Build Source Tree]
C[XSLT Stylesheet] --> D[Build Stylesheet Tree]
B --> E[Processor]
D --> E
E --> F[Match Template Rules]
F --> G[Generate Result Tree]
G --> H[Serialize Output]
Template Rules
Every XSLT transformation is built from template rules:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!-- Root template: matches the document root -->
<xsl:template match="/">
<html>
<body>
<h1>Library Catalog</h1>
<xsl:apply-templates select="library"/>
</body>
</html>
</xsl:template>
<!-- Template for library element -->
<xsl:template match="library">
<table border="1">
<tr>
<th>Title</th>
<th>Author</th>
<th>Year</th>
<th>Price</th>
</tr>
<xsl:apply-templates select="book"/>
</table>
</xsl:template>
<!-- Template for individual 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="price"/></td>
</tr>
</xsl:template>
</xsl:stylesheet>
Input XML
<?xml version="1.0" encoding="UTF-8"?>
<library>
<book category="fiction">
<title>The Hobbit</title>
<author>J.R.R. Tolkien</author>
<year>1937</year>
<price>12.99</price>
</book>
<book category="non-fiction">
<title>A Brief History of Time</title>
<author>Stephen Hawking</author>
<year>1988</year>
<price>9.99</price>
</book>
</library>
Expected HTML Output
<html>
<body>
<h1>Library Catalog</h1>
<table border="1">
<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</td>
</tr>
<tr>
<td>A Brief History of Time</td>
<td>Stephen Hawking</td>
<td>1988</td>
<td>9.99</td>
</tr>
</table>
</body>
</html>
Built-in Templates
When no matching template exists, XSLT applies built-in templates:
| Node Type | Built-in Behavior |
|---|---|
Root (/) |
Apply templates to children |
| Element | Apply templates to children |
| Text | Copy text to output |
| Attribute | Copy attribute value |
| Comment / PI | Nothing (skipped) |
These built-in templates explain why text content sometimes appears unexpectedly in output — the processor is using default rules.
Template Conflict Resolution
When multiple templates match the same node, XSLT uses priority rules:
<!-- Low priority: matches all books -->
<xsl:template match="book" priority="0">
<p>Book: <xsl:value-of select="title"/></p>
</xsl:template>
<!-- Higher priority: matches fiction books only -->
<xsl:template match="book["@category"='fiction']" priority="0.5">
<p>Fiction: <xsl:value-of select="title"/></p>
</xsl:template>
<!-- Default priority based on pattern specificity -->
<xsl:template match="book">
<!-- Default priority = 0 for simple patterns -->
</xsl:template>
Priority rules from highest to lowest:
- Explicit priority (the
priorityattribute) - Match specificity — more specific patterns win
- Document order — last declaration wins
Modes
Modes allow the same node to be processed multiple ways:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!-- Default mode: full listing -->
<xsl:template match="book">
<div class="book">
<xsl:apply-templates select="title"/>
<xsl:apply-templates select="author"/>
</div>
</xsl:template>
<!-- Summary mode: just titles -->
<xsl:template match="book" mode="summary">
<li><xsl:value-of select="title"/></li>
</xsl:template>
<!-- Table of contents -->
<xsl:template match="/">
<html>
<body>
<h2>Full Listing</h2>
<xsl:apply-templates select="//book"/>
<h2>Table of Contents</h2>
<ul>
<xsl:apply-templates select="//book" mode="summary"/>
</ul>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
Controlling Processing Order
The xsl:sort element controls the order of processed nodes:
<xsl:template match="library">
<ol>
<xsl:apply-templates select="book">
<!-- Sort by year ascending -->
<xsl:sort select="year" order="ascending"/>
</xsl:apply-templates>
</ol>
</xsl:template>
<xsl:template match="book">
<li>
<xsl:value-of select="title"/>
(<xsl:value-of select="year"/>)
</li>
</xsl:template>
Expected Output
<ol>
<li>The Hobbit (1937)</li>
<li>1984 (1949)</li>
<li>A Brief History of Time (1988)</li>
</ol>
Named Templates for Reusability
Named templates work like functions, called by name rather than matched:
<xsl:template match="/">
<html>
<body>
<xsl:call-template name="header"/>
<xsl:apply-templates select="library"/>
<xsl:call-template name="footer"/>
</body>
</html>
</xsl:template>
<xsl:template name="header">
<h1>Library Catalog</h1>
<p>Generated: <xsl:value-of select="'2026-06-23'"/></p>
</xsl:template>
<xsl:template name="footer">
<hr/>
<p>Built by DodaTech</p>
</xsl:template>
Named templates accept parameters:
<xsl:template name="format-price">
<xsl:param name="amount"/>
<xsl:param name="currency" select="'USD'"/>
<span class="price">
<xsl:value-of select="$currency"/> <xsl:value-of select="$amount"/>
</span>
</xsl:template>
<!-- Calling with parameters -->
<xsl:call-template name="format-price">
<xsl:with-param name="amount" select="price"/>
<xsl:with-param name="currency" select="price/@currency"/>
</xsl:call-template>
Security Angle
XSLT processors can execute arbitrary code through xsl:script or xsl:extension-element-prefixes — a serious security risk. Durga Antivirus Pro disables XSLT scripting extensions when processing untrusted stylesheets and validates all XSLT inputs against an allowlist of functions. Never process XSLT from untrusted sources without sandboxing, as malicious stylesheets can read files or execute system commands.
Common Mistakes
1. Forgetting xsl:apply-templates
If you match a template but don't call xsl:apply-templates, the processor stops. Children are not processed unless you explicitly tell it to continue.
2. Infinite recursion
A template that applies templates to itself creates infinite recursion. Ensure match and select don't loop back to the same node.
3. Confusing xsl:value-of with xsl:copy-of
xsl:value-of outputs the text content of a node. xsl:copy-of outputs the node including its children. Using value-of when you need copy-of drops child elements.
4. Wrong namespace declaration
Forgetting xmlns:xsl="http://www.w3.org/1999/XSL/Transform" causes the processor to ignore XSLT instructions and output them as plain text.
Practice Questions
What happens when no template matches a node in XSLT? The processor uses built-in templates: for elements, it applies templates to children; for text, it copies the text; for root, it processes children.
How do you process the same nodes differently in XSLT? Use modes. Templates with different mode attributes can process the same nodes in different ways, like one mode for full display and another for summaries.
What determines which template wins when multiple templates match the same node? Priority (explicit or implicit via pattern specificity), with explicit priority taking precedence and document order breaking ties.
Challenge: Write an XSLT stylesheet that converts a library XML into a JSON-like indented text format. Use modes to offer both full and compact output.
FAQ
Try It Yourself
Transform XML with Saxon on the command line:
# Install Saxon (Java-based XSLT processor)
# Then transform:
java -jar saxon9he.jar -s:library.xml -xsl:library.xsl -o:output.html
# Expected output:
# (writes output.html with the transformed HTML content)
# No terminal output on success
Use Python with lxml for XSLT transformations:
from lxml import etree
# Load XML and XSLT
xml = etree.parse("library.xml")
xslt = etree.parse("library.xsl")
transform = etree.XSLT(xslt)
# Apply transformation
result = transform(xml)
# Output as string
print(str(result))
# Expected:
# <?xml version="1.0"?>
# <html>
# <body>
# <h1>Library Catalog</h1>
# ...
# </body>
# </html>
What's Next
| Tutorial | What You'll Learn |
|---|---|
| XSLT Explained — Transform XML | Basics of XSLT transformation |
| XPath Explained — Querying XML | Navigate XML documents with path expressions |
| XML Basics — Complete Guide | Foundational XML concepts |
Built by the developers of Doda Browser, DodaZIP, and Durga Antivirus Pro. Updated 2026-06-23.
What's Next
Congratulations on completing this XSLT Processing Model tutorial! Here's where to go from here:
- Practice daily — Consistency is more important than long study sessions
- Build a project — Transform an RSS feed into styled HTML
- Explore related topics — Check out other XML tutorials in this 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