How xsl:next-match Improves XSLT Template Delegation
The xsl:next-match instruction introduced in XSLT 2.0
and refined in XSLT 3.0 dramatically enhances template delegation by
allowing a stylesheet to invoke the next-best matching template rule for
the current item. In earlier versions of XSLT, developers relied almost
exclusively on xsl:apply-imports, which imposed strict
structural limits by requiring delegated templates to reside in
separately imported files. With xsl:next-match, XSLT
developers gain a native mechanism to implement layered processing,
aspect-oriented transformations, and the decorator pattern directly
within single or modular stylesheets based on rule priorities and import
precedence.
The Limitation of
XSLT 1.0: xsl:apply-imports
In XSLT 1.0, the only built-in mechanism for delegating execution to
an overridden rule was <xsl:apply-imports/>. While
useful for overriding rules defined in imported stylesheets, it had two
critical shortcomings: 1. Physical File Dependency: It
could only delegate to templates in imported stylesheets with lower
import precedence. It was impossible to delegate to another matching
template located within the same stylesheet module. 2. Priority
Blindness: It completely ignored explicit
@priority attributes when determining delegation targets,
relying solely on the import tree hierarchy.
These restrictions forced developers to create artificial modular file structures or invent complex custom modes simply to achieve multi-step processing or element wrapping.
How
xsl:next-match Solves Template Delegation
The <xsl:next-match> instruction evaluates all
template rules that match the current node or atomic item and selects
the one with the next-highest precedence or priority.
When an xsl:template executes
xsl:next-match, the XSLT processor: 1. Identifies all
candidate templates that match the current item and match the current
mode (if specified). 2. Excludes the currently executing template and
any templates with higher precedence or priority. 3. Selects and
executes the template that would have matched if the current template
did not exist.
Key Benefits
1. In-File Template Chaining
Developers can define multiple templates matching the same node with
different @priority values in the same file. A
high-priority template can perform pre-processing, execute
xsl:next-match to let the default rule generate the base
markup, and then perform post-processing.
<!-- Generic rule for all fields -->
<xsl:template match="field" priority="1">
<input type="text" name="{@name}" value="{@value}"/>
</xsl:template>
<!-- Specialized rule adding a wrapper without duplicating base logic -->
<xsl:template match="field[@required = 'true']" priority="2">
<div class="required-wrapper">
<xsl:next-match/>
<span class="required-indicator">*</span>
</div>
</xsl:template>2. Robust Parameter Passing
Like xsl:apply-templates, xsl:next-match
allows passing parameters via <xsl:with-param>. This
includes support for tunnel parameters (tunnel="yes"),
enabling context data to pass seamlessly through layers of delegated
templates without requiring manual forwarding at every intermediate
step.
3. Support for Typed Items and Functions in XSLT 3.0
In XSLT 3.0, xsl:next-match extends beyond XML nodes to
process atomic values, maps, and arrays when using matching templates
within sequence-based pipelines. It also works in conjunction with
private modes and package visibility, ensuring that delegation respects
module encapsulation.
4. Clean Implementation of the Decorator Pattern
By removing the need for auxiliary modes or artificial file
splitting, xsl:next-match makes it simple to write
interceptor-style rules. This is particularly valuable in document
processing pipelines (such as HTML or DocBook conversion), where
specific element instances need structural enhancements or metadata
annotations while preserving standard transformation behavior.