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:

  1. Defining the Template Rule: You attach the mode attribute 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>
  2. 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