How to Process XML Nodes Multiple Times in XSLT
In XSLT, template modes enable developers to process the same XML
node-set multiple times within a single stylesheet to generate distinct
representations or layouts. By assigning a mode attribute
to both template rules and template calls, XSLT segregates
transformation logic, allowing identical nodes to match different
templates depending on the specific output context required.
The Conflict of Default Processing
In standard XSLT transformations without modes, each XML node
typically matches only one template rule with the highest priority or
specificity. If you attempt to write multiple
<xsl:template match="section"> blocks to render the
same content differently (such as a full article view and a condensed
table of contents entry), the XSLT processor considers them conflicting
rules for the same nodes in the default processing mode.
How Template Modes Work
The mode attribute provides a namespace-like
categorization for template rules:
Defining the Template Rule: You attach the
modeattribute to the<xsl:template>declaration:<!-- Mode for generating a Table of Contents --> <xsl:template match="chapter" mode="toc"> <li><a href="#{generate-id()}"><xsl:value-of select="title"/></a></li> </xsl:template> <!-- Mode for rendering the full content --> <xsl:template match="chapter" mode="full-content"> <section id="{generate-id()}"> <h2><xsl:value-of select="title"/></h2> <xsl:apply-templates select="paragraph"/> </section> </xsl:template>Invoking the Mode: When calling
<xsl:apply-templates>, you specify which mode to execute:<!-- First pass: Table of Contents --> <ul> <xsl:apply-templates select="//chapter" mode="toc"/> </ul> <!-- Second pass: Full Document Body --> <main> <xsl:apply-templates select="//chapter" mode="full-content"/> </main>
Key Advantages
- Independent Transformation Streams: Different modes operate independently, meaning node-sets can be traversed repeatedly to create tables of contents, summaries, indexes, footnotes, or alternative views without altering the underlying source XML.
- Preservation of Context: The context node, position, and hierarchy are preserved during each pass, enabling relative XPath navigation and dynamic ID generation (such as internal hyperlinks) across different passes.
- Separation of Concerns: Modes prevent complex
conditional logic (
<xsl:if>or<xsl:choose>) inside a single monolithic template, resulting in modular, maintainable stylesheets.