How Does xsl:next-match Improve on apply-imports?

In XSLT stylesheet development, delegating processing to lower-priority or imported rules has evolved significantly between versions. While XSLT 1.0 introduced <xsl:apply-imports> to let overriding templates invoke the definitions they hid in imported stylesheets, XSLT 2.0 addressed fundamental limitations of this mechanism by introducing <xsl:next-match>. This article examines how <xsl:next-match> simplifies modular development, eliminates strict import-tree restrictions, supports dynamic parameter passing, and accommodates same-stylesheet priority chaining.

The Limitations of xsl:apply-imports

To understand the improvements introduced in XSLT 2.0, it helps to examine the architectural constraints of <xsl:apply-imports>:

Core Advantages of xsl:next-match

XSLT 2.0 introduced <xsl:next-match> to provide a general-purpose, predictable mechanism for delegating execution down the template priority chain.

1. Same-Module Priority Chaining

Unlike <xsl:apply-imports>, <xsl:next-match> does not require separate files linked via <xsl:import>. It searches the entire set of matching templates for the current node and invokes the rule with the next highest precedence or priority, even if that template is declared in the exact same stylesheet module.

For example, you can define specific and general templates within one file:

<!-- Higher priority rule for special formatting -->
<xsl:template match="para[@class='highlight']" priority="2">
  <div class="highlight-wrapper">
    <xsl:next-match/>
  </div>
</xsl:template>

<!-- Base fallback rule -->
<xsl:template match="para" priority="1">
  <p><xsl:apply-templates/></p>
</xsl:template>

When processing a <para class="highlight">, the higher-priority template executes first, wraps the output, and calls <xsl:next-match/> to run the base paragraph formatting rule seamlessly.

2. Native Parameter Passing

<xsl:next-match> fully supports passing parameters to the next matching template using <xsl:with-param>. This allows delegating templates to compute intermediate values or modify execution state before handing off execution:

<xsl:template match="item[@featured='true']">
  <xsl:next-match>
    <xsl:with-param name="isSpecial" select="true()" />
  </xsl:next-match>
</xsl:template>

<xsl:template match="item">
  <xsl:param name="isSpecial" select="false()" />
  <li class="{if ($isSpecial) then 'featured-item' else 'standard-item'}">
    <xsl:apply-templates/>
  </li>
</xsl:template>

3. Clearer Conflict and Precedence Resolution

The evaluation semantics for <xsl:next-match> follow a consistent resolution hierarchy based on:

  1. Import Precedence: Higher import levels are evaluated first.
  2. Template Priority: Explicit @priority attributes or default XSLT pattern priorities.
  3. Declaration Order: When priority and precedence match, the last declared template in document order wins.

Because this ordering applies uniformly, <xsl:next-match> steps down to the immediate runner-up template under these exact rules without requiring custom pipeline workarounds.

Direct Comparison

Feature <xsl:apply-imports> <xsl:next-match>
Introduced In XSLT 1.0 XSLT 2.0
Same-stylesheet Delegation No Yes
Parameter Passing (xsl:with-param) No (in XSLT 1.0) Yes
Resolution Basis Import tree only Import precedence + template priority
Use Case Focus Legacy import layering Comprehensive template composition

By removing file boundary dependencies and integrating full parameter support, <xsl:next-match> turns template delegation into a flexible design pattern for clean, composable XSLT stylesheets.