Using xsl:apply-imports for XSLT Inheritance
This article explores the xsl:apply-imports instruction
in XSLT, explaining its purpose, mechanics, and role in creating
modular, reusable XML stylesheets. You will learn how template import
precedence works, how xsl:apply-imports enables an
object-oriented style of template inheritance similar to
super() calls in programming languages, and how to
effectively override base stylesheet templates while preserving their
core functionality.
What is xsl:apply-imports?
The xsl:apply-imports element is an XSLT instruction
used to invoke an overridden template rule from an imported stylesheet
module. When stylesheets are combined using
<xsl:import>, rules defined in the importing (main)
stylesheet automatically take precedence over rules with the same match
pattern in the imported (base) stylesheet.
By using xsl:apply-imports, a developer can selectively
execute the imported, lower-precedence template rule for the current
context node, allowing the importing stylesheet to wrap or augment base
behavior rather than completely replacing it.
How Import Precedence Works
In modular XSLT architecture, stylesheets are aggregated using either
<xsl:include> or <xsl:import>:
xsl:include: Inlines templates as if they were written directly in the main stylesheet, treating all templates with equal import precedence.xsl:import: Establishes a strict hierarchy. Templates in the importing stylesheet have higher import precedence than templates in the imported stylesheet.
When the XSLT processor encounters multiple matching templates with
identical priority and specificity, it selects the template with the
highest import precedence. Without xsl:apply-imports, the
base template in the imported module is completely shadowed.
Supporting Inheritance in Modular Stylesheets
xsl:apply-imports enables classic inheritance and
polymorphism in XSLT transformations:
1. Specialization and Extension
Similar to calling super.method() in object-oriented
programming, xsl:apply-imports allows a specialized
stylesheet to execute standard transformations defined in a shared base
stylesheet, adding customized markup before or after the base
output.
2. Separation of Concerns
Organizations can maintain a central library of standard templates defining corporate XML-to-HTML/PDF rules, while individual departments import the library and override only the specific elements they need to customize.
3. Maintainability
If standard processing logic changes in the base stylesheet, all
downstream stylesheets utilizing xsl:apply-imports
automatically inherit the updates without manual code duplication.
Code Example: Extending a Base Template
Base Stylesheet
(base.xsl)
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="note">
<div class="note">
<p><xsl:value-of select="body"/></p>
</div>
</xsl:template>
</xsl:stylesheet>Custom Stylesheet
(custom.xsl)
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:import href="base.xsl"/>
<xsl:template match="note">
<div class="custom-wrapper">
<h3>Notice: <xsl:value-of select="@type"/></h3>
<!-- Delegate the core rendering to the imported base template -->
<xsl:apply-imports/>
</div>
</xsl:template>
</xsl:stylesheet>In this scenario, the XML
<note type="warning"><body>Alert text</body></note>
will output the customized header (<h3>) followed by
the original <div> structure rendered by
base.xsl.
Key Rules and Limitations
- Context Node Constraint:
xsl:apply-importsautomatically operates on the current node. You cannot pass aselectattribute to change the target node. - Mode Matching: The imported template must match the current node in the current processing mode.
- Parameter Passing: In XSLT 1.0,
xsl:apply-importscannot pass parameters to the imported template using<xsl:with-param>. Support for passing parameters was introduced in XSLT 2.0. - Evolution to
xsl:next-match: Whilexsl:apply-importsonly delegates to templates with lower import precedence, XSLT 2.0 and later introducedxsl:next-match, which can delegate to templates with lower priority within the same stylesheet as well as across imported modules.