Chapter 59: XSLT – Transformation
1. What does “transformation” really mean in XSLT?
Transformation = taking one document (almost always XML) and producing a completely new document from it.
The new document can be:
- another XML document (different structure, different tags, filtered content…)
- HTML (most common real use case)
- plain text (CSV, email body, log file…)
- JSON (XSLT 3.0+)
- PDF (indirectly via XSL-FO)
Most important mindset to adopt right now:
XSLT is not a general-purpose programming language like Python or JavaScript. It is a declarative, rule-based, pattern-matching language.
You don’t write:
|
0 1 2 3 4 5 6 7 8 |
for each book: print the title if price > 1000 then print "expensive" |
Instead you write:
|
0 1 2 3 4 5 6 7 |
When you see a <book> element, output its <title> When you see a <price> that is > 1000, add the word "expensive" |
The XSLT processor reads your input XML, finds matching patterns, and applies your rules — in the order it finds them, following a very specific processing model.
2. The absolute minimal transformation (copy-paste & understand)
|
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 |
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- Tell the processor what kind of output we want --> <xsl:output method="html" indent="yes" encoding="UTF-8"/> <!-- This is the entry point: matches the root of ANY input document --> <xsl:template match="/"> <html> <head> <title>Hello from XSLT</title> </head> <body> <h1>This page was created by XSLT</h1> <p>Even if your input XML is completely empty, I still produce this.</p> <p>Current date/time: <xsl:value-of select="current-dateTime()"/></p> </body> </html> </xsl:template> </xsl:stylesheet> |
What happens inside the processor?
- It starts reading any input XML document
- It looks for a template that matches the root of the document (/)
- It finds this template → runs the code inside
- It outputs the HTML — even if the input was <nothing/>
This is the starting point of every XSLT transformation.
3. Real example 1 – Transform product list into nice HTML table
Input XML (products.xml)
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
<?xml version="1.0" encoding="UTF-8"?> <catalog> <product> <name>Wireless Mouse</name> <price currency="INR">1499.00</price> <stock>45</stock> </product> <product> <name>USB-C Hub</name> <price currency="INR">2499.00</price> <stock>12</stock> </product> <product> <name>Mechanical Keyboard</name> <price currency="INR">3999.00</price> <stock>8</stock> </product> </catalog> |
XSLT stylesheet (products-to-html.xsl)
|
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 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- Output format --> <xsl:output method="html" indent="yes" encoding="UTF-8"/> <!-- Root template – entry point --> <xsl:template match="/"> <html> <head> <title>Product Catalog</title> <style> table { border-collapse: collapse; width: 80%; margin: 20px auto; font-family: Arial; } th, td { border: 1px solid #ccc; padding: 10px; text-align: left; } th { background-color: #f0f0f0; } .low-stock { color: red; font-weight: bold; } .good-stock { color: green; } </style> </head> <body> <h1>Current Product Catalog</h1> <table> <tr> <th>Name</th> <th>Price</th> <th>Stock</th> <th>Status</th> </tr> <!-- Process every <product> --> <xsl:apply-templates select="catalog/product"/> </table> <p style="text-align:center; margin-top:30px;"> Generated on <xsl:value-of select="current-dateTime()"/> </p> </body> </html> </xsl:template> <!-- Template that runs for each <product> --> <xsl:template match="product"> <tr> <td><xsl:value-of select="name"/></td> <td> <xsl:value-of select="price"/> <xsl:text> </xsl:text> <xsl:value-of select="price/@currency"/> </td> <td> <xsl:value-of select="stock"/> </td> <td> <xsl:choose> <xsl:when test="stock = 0"> <span style="color:red">Out of stock</span> </xsl:when> <xsl:when test="stock &lt; 20"> <span class="low-stock">Low stock (<xsl:value-of select="stock"/> left)</span> </xsl:when> <xsl:otherwise> <span class="good-stock">In stock</span> </xsl:otherwise> </xsl:choose> </td> </tr> </xsl:template> </xsl:stylesheet> |
Result HTML (what you see in browser)
|
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 |
<html> <head>...</head> <body> <h1>Current Product Catalog</h1> <table> <tr><th>Name</th><th>Price</th><th>Stock</th><th>Status</th></tr> <tr> <td>Wireless Mouse</td> <td>1499.00 INR</td> <td>45</td> <td><span class="good-stock">In stock</span></td> </tr> <tr> <td>USB-C Hub</td> <td>2499.00 INR</td> <td>12</td> <td><span class="low-stock">Low stock (12 left)</span></td> </tr> <tr> <td>Mechanical Keyboard</td> <td>3999.00 INR</td> <td>8</td> <td><span class="low-stock">Low stock (8 left)</span></td> </tr> </table> <p style="text-align:center; margin-top:30px;"> Generated on 2025-07-28T14:35:22.123+05:30 </p> </body> </html> |
Lesson 4 – Core concepts you must understand deeply
4.1 The processing model – how XSLT really works
- Processor starts at the root of the input XML (/)
- Looks for a template that matches the root (match=”/”)
- Executes the code inside that template
- When it sees <xsl:apply-templates select=”something”/> → it pauses, finds all matching nodes, and for each one:
- looks for the best matching template
- runs it
- continues
- When no more templates apply → finishes
This is why XSLT feels “automatic” — you define rules, and the processor walks the tree for you.
4.2 <xsl:value-of select=”…”/> – the most used instruction
|
0 1 2 3 4 5 6 7 8 9 |
<xsl:value-of select="price"/> <xsl:value-of select="price/@currency"/> <xsl:value-of select="concat('Rs. ', price * 1.18)"/> <xsl:value-of select="format-number(price, '#,##0.00')"/> |
4.3 <xsl:apply-templates> vs <xsl:for-each>
|
0 1 2 3 4 5 6 7 8 9 10 11 12 |
<!-- Recommended style – more modular --> <xsl:apply-templates select="product"/> <!-- Classic loop style – use only when needed --> <xsl:for-each select="product"> <tr><td><xsl:value-of select="name"/></td></tr> </xsl:for-each> |
Rule of thumb: Use apply-templates when you want reusability and hierarchy Use for-each when you want strict control over order or simple flat lists
Lesson 5 – Try yourself exercises (do these!)
- Output only the product names in a bullet list
- Show name + price with currency symbol
- If stock < 20, show “Low stock!” in red
- Create a table with columns: Name, Price, Stock, Status
- Add a message “Free shipping” if price > 2000
- Show only products from category “electronics”
Lesson 6 – Real-world context (where XSLT is still used in 2025–2026)
- e-Invoicing — GST XML → human-readable HTML/PDF
- Financial messages — ISO 20022 → reports
- Publishing — DocBook/DITA → HTML/PDF/EPUB
- Legacy SOAP services — transform XML → preview
- EDI / B2B — EDIFACT → XML → confirmation page
- Configuration — XML config → documentation
Would you like to continue with one of these next?
- Identity transform (copy everything + make small changes)
- Grouping (group products by category – XSLT 2.0/3.0)
- Variables & parameters
- XSLT with namespaces (real e-invoice, SOAP, Android manifest…)
- XSLT 1.0 vs 2.0 vs 3.0 – what’s new & why it matters
- Real-world example — GST invoice → nice HTML
Just tell me which direction feels most useful or interesting for you right now! 😊
