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>:
- Strict Import Dependency:
<xsl:apply-imports>only invokes templates defined inside explicitly imported stylesheets (via<xsl:import>). It completely ignores matching templates with lower explicit or default priorities within the same stylesheet module. - No Inline Parameter Passing: In standard XSLT 1.0,
<xsl:apply-imports>does not permit child<xsl:with-param>elements. Downstream templates must rely entirely on global state or tunnel values present from the initial invocation. - Rigid Overriding Rules: If two templates exist in
the same module matching the same pattern with different
@priorityattributes,<xsl:apply-imports>cannot bridge the gap between the higher-priority rule and the fallback lower-priority rule.
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:
- Import Precedence: Higher import levels are evaluated first.
- Template Priority: Explicit
@priorityattributes or default XSLT pattern priorities. - 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.