How Did XSLT 3.0 Enhance Template Modes?
XSLT 3.0 transformed template matching by turning modes from
lightweight labels into formal, configurable processing pipelines.
Through the introduction of the top-level <xsl:mode>
declaration, special mode tokens like #all and
#default, and explicit schema-typing controls such as
typed="untyped", the specification eliminated extensive
boilerplate code, improved modularity in stylesheet packages, and
simplified streaming architectures.
Explicit Mode
Configuration with xsl:mode
In earlier versions of XSLT, modes were declared implicitly whenever
a template specified a mode attribute. XSLT 3.0 introduced
the <xsl:mode> declaration, allowing developers to
define global behaviors, visibility, and execution strategies for named
and unnamed modes:
<xsl:mode name="transform-pass" on-no-match="shallow-copy" streamable="no"/>This explicit declaration controls several operational aspects:
- Built-in Template Behavior: The
on-no-matchattribute defines what happens when no explicit template matches a node (e.g.,shallow-copy,deep-copy,shallow-skip,deep-skip,fail, ortext-only-copy). - Modularity and Visibility: Modes can be scoped with
visibility levels (
public,private,final) to control how templates are inherited or overridden across XSLT packages. - Streaming Constraints: Setting
streamable="yes"enforces static rules to ensure input documents can be processed in a single pass without loading the full tree into memory.
Targeting Modes with
#default
The #default token provides a standardized way to
reference the unnamed, default processing mode. This token can be used
in the mode attribute of <xsl:template>
and <xsl:apply-templates>:
<!-- Matches the element in both the default unnamed mode and a specific named mode -->
<xsl:template match="para" mode="#default summary-pass">
<p><xsl:apply-templates/></p>
</xsl:template>Additionally, stylesheets can define module-wide defaults using the
default-mode attribute on
<xsl:stylesheet>, redirecting un-annotated
<xsl:template> and
<xsl:apply-templates> instructions to any named mode
without manual tag-by-tag updates.
Universal Rule Application
with #all
The #all keyword allows a single template rule to apply
across all existing modes in the stylesheet:
<xsl:template match="comment() | processing-instruction()" mode="#all"/>When a template is marked with mode="#all", the XSLT
processor copies that rule into every declared or referenced mode. This
eliminates the need to duplicate utility rules (such as stripping
comments, normalizing text, or emitting debugging signals) across
multi-pass transformation pipelines.
Declaring Data Types
with typed="untyped"
XSLT 3.0 introduced the typed attribute on
<xsl:mode> to declare whether template rules in that
mode expect schema-validated or untyped input:
<xsl:mode name="ingest-mode" typed="untyped"/>Setting typed="untyped" asserts that nodes processed by
the mode have not undergone schema validation. This gives the processor
static information that all elements and attributes match
xs:untyped and xs:untypedAtomic, bypassing
type-checking overhead and enabling optimized path navigation and
pattern matching.
The Built-in Identity Revolution
Prior to XSLT 3.0, performing an identity transformation with selective overrides required writing an explicit identity template. With XSLT 3.0, a complete identity transform mode requires only a single line:
<xsl:mode on-no-match="shallow-copy"/>By combining on-no-match="shallow-copy",
#default, and #all, developers can write
focused stylesheets containing only the rules for nodes that require
modification, while the underlying mode infrastructure handles recursive
document copying automatically.