Chapter 60: XSLT
1. What is <xsl:template> really? (the heart of XSLT)
The <xsl:template> element is the most important building block of every XSLT stylesheet.
It is the place where you define:
“When the processor sees this kind of node (or this pattern), then output this content (and maybe process children in a certain way).”
Think of <xsl:template> as a recipe card in a huge kitchen (the XML document).
Each recipe card says:
- Trigger: when you see this ingredient / this dish being prepared…
- Instructions: …then do these steps (output HTML, copy text, create new elements, call other recipes…)
The XSLT processor walks through the input XML and whenever it finds a node that matches one of your template triggers, it executes that template.
2. Two completely different ways to write a template
There are two main styles of <xsl:template> — beginners often mix them up.
| Style | Syntax example | When the template runs | Most common use case | Typical in… |
|---|---|---|---|---|
| Match template | <xsl:template match=”book”> … </xsl:template> | When the processor is processing a <book> node | The classic, most powerful style | 95% of real stylesheets |
| Named template | <xsl:template name=”format-price”> … </xsl:template> | Only when you explicitly call it with <xsl:call-template name=”format-price”/> | Reusable helper functions (like functions in other languages) | Helper logic |
Rule to remember forever:
Most of your templates should be match templates (match=”…”) Named templates (name=”…”) are like utility functions — use them when you want to reuse the same logic in many places
3. Anatomy of a <xsl:template match=”…”> (most important style)
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
<xsl:template match="product"> <!-- This block is executed every time the processor is processing a <product> element in the input document. --> <!-- Output HTML or new XML --> <div class="product-card"> <!-- Copy values from the current context --> <h3><xsl:value-of select="name"/></h3> <!-- Output attribute value --> <p class="price"> <xsl:value-of select="price"/> <xsl:text> </xsl:text> <xsl:value-of select="price/@currency"/> </p> <!-- Conditional content --> <xsl:if test="stock &lt; 10"> <span class="warning">Low stock!</span> </xsl:if> <!-- Process children using their own templates --> <xsl:apply-templates select="description"/> </div> </xsl:template> |
What happens when the processor sees a <product>?
- It finds this template (because match=”product”)
- It executes everything inside the template
- When it reaches <xsl:apply-templates select=”description”/> → it pauses, looks for a template that matches <description>, runs it, then continues
4. Real example 1 – Simple product → nice HTML card
Input XML
|
0 1 2 3 4 5 6 7 8 9 10 11 12 |
<catalog> <product> <name>Wireless Mouse</name> <price currency="INR">1499.00</price> <stock>45</stock> </product> </catalog> |
XSLT
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="html" indent="yes"/> <!-- Entry point: root of the document --> <xsl:template match="/"> <html> <head><title>Product</title></head> <body> <h1>Product Details</h1> <xsl:apply-templates select="catalog/product"/> </body> </html> </xsl:template> <!-- This template is called for every <product> --> <xsl:template match="product"> <div style="border:1px solid #ccc; padding:16px; margin:16px; max-width:400px;"> <h2><xsl:value-of select="name"/></h2> <p> Price: <strong><xsl:value-of select="price"/></strong> <xsl:text> </xsl:text> <xsl:value-of select="price/@currency"/> </p> <p> Stock: <xsl:choose> <xsl:when test="stock &lt; 10"> <span style="color:red"><xsl:value-of select="stock"/> (Low!)</span> </xsl:when> <xsl:otherwise> <xsl:value-of select="stock"/> </xsl:otherwise> </xsl:choose> </p> </div> </xsl:template> </xsl:stylesheet> |
Result HTML
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<html> <body> <h1>Product Details</h1> <div style="border:1px solid #ccc; padding:16px; margin:16px; max-width:400px;"> <h2>Wireless Mouse</h2> <p>Price: <strong>1499.00</strong> INR</p> <p>Stock: 45</p> </div> </body> </html> |
Lesson 5 – The most important pattern: push style vs pull style
There are two philosophies in XSLT — beginners often mix them.
Push style (preferred – more XSLT-like)
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
<xsl:template match="/"> <html> <body> <xsl:apply-templates/> <!-- let the processor decide what to do next --> </body> </html> </xsl:template> <xsl:template match="product"> <div class="product"> <xsl:apply-templates/> <!-- process children --> </div> </xsl:template> <xsl:template match="name"> <h3><xsl:value-of select="."/></h3> </xsl:template> |
→ The processor pushes the nodes through the templates automatically
Pull style (more like traditional programming)
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<xsl:template match="/"> <html> <body> <xsl:for-each select="catalog/product"> <div class="product"> <h3><xsl:value-of select="name"/></h3> <p>₹<xsl:value-of select="price"/></p> </div> </xsl:for-each> </body> </html> </xsl:template> |
→ You pull the data exactly where you want it
Rule of thumb (very useful in practice)
- Use push style (apply-templates) when you want modular, reusable rules and natural hierarchy
- Use pull style (for-each, value-of) when you want strict control over layout and order
Lesson 6 – Try yourself exercises (do these!)
- Create a simple HTML page that shows only product names in <h2> tags
- Show name + price with currency symbol
- If stock < 20, add a red “Low stock!” warning
- Make a table with columns: Name | Price | Stock | Status
- Add “Free shipping” message if price > 2000
- Show only products with stock > 0
Lesson 7 – Real-world context (where XSLT is still very much used in 2025–2026)
- Mandatory e-Invoicing — GST, PEPPOL, Factur-X, ZUGFeRD → XML → nice HTML/PDF
- Financial messages — ISO 20022 payment files → human-readable reports
- Publishing — DocBook, DITA, JATS → HTML, PDF, EPUB
- Legacy enterprise integration — SOAP responses → preview / logging
- EDI / B2B — transform incoming XML → confirmation email / PDF
- Technical documentation — XML config → styled documentation
Would you like to continue with one of these next?
- Identity transform (copy almost everything + make small changes)
- Grouping (group products by category – XSLT 2.0/3.0)
- Variables and parameters
- XSLT with namespaces (real e-invoice, SOAP, HL7, Android manifest…)
- XSLT 1.0 vs 2.0 vs 3.0 – what changed and why it matters
- Real-world example — GST e-invoice XML → beautiful HTML invoice
Just tell me which direction feels most useful or interesting for you right now! 😊
