XSLT - Using <xsl:apply-imports> in Imported Stylesheets

Introduction

In XSLT, stylesheets can be divided into multiple files and combined using <xsl:import>. This is useful when a large XSLT project needs to be organized into smaller, reusable stylesheet modules.

When one stylesheet imports another stylesheet, the importing stylesheet can override templates defined in the imported stylesheet. The <xsl:apply-imports> instruction provides a way for the overriding template to call the version of the template that was defined in the imported stylesheet.

In simple terms, <xsl:apply-imports> means:

"Use the template from the imported stylesheet instead of the overriding template that is currently being used."

It is particularly useful when you want to modify or extend existing XSLT behavior without completely replacing it.


1. Understanding <xsl:import>

Before understanding <xsl:apply-imports>, it is important to understand stylesheet importing.

The <xsl:import> element allows one XSLT stylesheet to use another stylesheet.

For example:

<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:import href="base.xsl"/>

</xsl:stylesheet>

Here:

  • base.xsl is the imported stylesheet.

  • The current stylesheet is the importing stylesheet.

  • Templates defined in base.xsl become available to the importing stylesheet.

This approach is useful when a common transformation needs to be reused across several projects.


2. What Happens When Templates Have the Same Match Pattern?

Suppose the imported stylesheet contains:

<xsl:template match="product">
    <div>
        <h2>Product Details</h2>
    </div>
</xsl:template>

Now suppose the importing stylesheet also contains:

<xsl:template match="product">
    <div>
        <h2>Product Information</h2>
    </div>
</xsl:template>

Both templates match the same product element.

Normally, the template in the importing stylesheet takes precedence over the template in the imported stylesheet.

Therefore, the imported template is overridden.

This behavior allows a developer to customize a general-purpose stylesheet.


3. The Purpose of <xsl:apply-imports>

The <xsl:apply-imports> instruction allows the overriding template to invoke the overridden template from the imported stylesheet.

For example:

<xsl:template match="product">
    <div class="highlight">
        <xsl:apply-imports/>
    </div>
</xsl:template>

Here, the current stylesheet has overridden the product template.

Instead of completely replacing the original behavior, it adds a <div class="highlight"> around the result produced by the imported template.

The imported template can therefore still perform its original transformation.


4. Simple Example

Consider the following XML document:

<catalog>
    <product>
        <name>Laptop</name>
        <price>75000</price>
    </product>
</catalog>

Suppose the base stylesheet contains:

<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:template match="product">
        <div>
            <h2>
                <xsl:value-of select="name"/>
            </h2>
            <p>
                Price:
                <xsl:value-of select="price"/>
            </p>
        </div>
    </xsl:template>

</xsl:stylesheet>

The imported stylesheet provides the basic product formatting.

Now the main stylesheet imports it:

<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:import href="base.xsl"/>

    <xsl:template match="product">
        <section class="product">
            <xsl:apply-imports/>
        </section>
    </xsl:template>

</xsl:stylesheet>

The main stylesheet overrides the product template.

However, instead of rewriting the entire product transformation, it uses:

<xsl:apply-imports/>

This tells the processor to execute the matching template from base.xsl.


5. Result of the Transformation

The output can look like:

<section class="product">
    <div>
        <h2>Laptop</h2>
        <p>Price: 75000</p>
    </div>
</section>

The outer <section> comes from the overriding template.

The inner <div>, <h2>, and <p> come from the imported template.

This demonstrates the main purpose of <xsl:apply-imports>: extend existing transformation behavior rather than completely replacing it.


6. Difference Between <xsl:apply-templates> and <xsl:apply-imports>

These two instructions may look similar, but they have different purposes.

<xsl:apply-templates>

This selects nodes and asks the XSLT processor to find the appropriate template for those nodes.

Example:

<xsl:apply-templates select="product"/>

The processor searches for the appropriate matching template according to normal template-selection rules.

<xsl:apply-imports>

This specifically tells the processor to use an applicable template from an imported stylesheet with lower import precedence.

Example:

<xsl:apply-imports/>

It is therefore primarily used when a template in the current stylesheet overrides a template from an imported stylesheet.


7. Import Precedence

The concept of import precedence is central to understanding <xsl:apply-imports>.

Suppose there are three stylesheets:

base.xsl
   ↓
theme.xsl
   ↓
main.xsl

theme.xsl imports base.xsl, while main.xsl imports theme.xsl.

The stylesheet closer to the main importing stylesheet has higher import precedence.

Therefore:

main.xsl
    Higher precedence

theme.xsl
    Lower precedence

base.xsl
    Lowest precedence

If main.xsl defines a template that overrides one from theme.xsl, <xsl:apply-imports> can invoke the lower-precedence template.


8. Why Is This Useful?

One major advantage of <xsl:apply-imports> is that it supports stylesheet customization.

Imagine a company has a common stylesheet used for generating reports.

The common stylesheet may contain:

<xsl:template match="employee">
    ...
</xsl:template>

A particular department may want to add additional formatting around the employee information.

Instead of copying the entire template, the department's stylesheet can override it:

<xsl:template match="employee">
    <div class="department-employee">
        <xsl:apply-imports/>
    </div>
</xsl:template>

This avoids duplicating the original transformation logic.


9. Avoiding Code Duplication

Without <xsl:apply-imports>, developers may copy the complete original template into the new stylesheet.

For example, they might copy:

<xsl:template match="employee">
    <div>
        <h2>
            <xsl:value-of select="name"/>
        </h2>
        <p>
            <xsl:value-of select="department"/>
        </p>
        <p>
            <xsl:value-of select="salary"/>
        </p>
    </div>
</xsl:template>

Then modify it.

This creates duplicate code.

If the original stylesheet changes later, the copied version may become outdated.

Using <xsl:apply-imports> avoids this problem because the original template remains in the imported stylesheet.


10. Adding Additional Processing

An overriding template can perform additional processing before calling the imported template.

Example:

<xsl:template match="product">

    <h1>Featured Product</h1>

    <xsl:apply-imports/>

</xsl:template>

The imported template continues to generate the normal product information.

The new stylesheet simply adds additional content before it.


11. Adding Processing After the Imported Template

You can also perform processing after <xsl:apply-imports>.

Example:

<xsl:template match="product">

    <xsl:apply-imports/>

    <p>Additional product information</p>

</xsl:template>

The imported template is executed first.

Then the additional paragraph is generated.

This allows developers to extend the original transformation both before and after the imported template's output.


12. Important Difference from <xsl:next-match>

In modern XSLT, <xsl:next-match> can also be used to invoke another matching template.

However, it is important not to confuse the two instructions.

<xsl:apply-imports> is based specifically on import precedence.

<xsl:next-match> searches for the next applicable template according to the template-matching rules.

Therefore, <xsl:apply-imports> is particularly appropriate when working with a layered stylesheet architecture where one stylesheet imports and overrides another.


13. Where <xsl:apply-imports> Is Commonly Used

It can be useful in several situations:

Reusable stylesheet frameworks

A common base stylesheet can provide standard transformation rules, while individual projects customize selected templates.

Report generation

A general reporting stylesheet can define common formatting, while individual departments add their own presentation requirements.

Website transformation

A base stylesheet can define standard HTML output, while another stylesheet modifies particular sections.

XML publishing systems

A common transformation framework can be customized for different document types.

Large XSLT projects

Large projects can separate common transformation rules from project-specific rules.


14. Important Syntax

The basic syntax is:

<xsl:apply-imports/>

Unlike <xsl:apply-templates>, it normally does not require a select attribute.

It operates on the current node and invokes an appropriate template from an imported stylesheet with lower import precedence.


15. A Complete Example

XML input

<catalog>
    <product>
        <name>Tablet</name>
        <price>30000</price>
    </product>
</catalog>

Base stylesheet: base.xsl

<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:template match="product">
        <div>
            <h2>
                <xsl:value-of select="name"/>
            </h2>

            <p>
                Price:
                <xsl:value-of select="price"/>
            </p>
        </div>
    </xsl:template>

</xsl:stylesheet>

Main stylesheet

<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:import href="base.xsl"/>

    <xsl:template match="product">
        <article>
            <h1>Product Details</h1>

            <xsl:apply-imports/>

        </article>
    </xsl:template>

</xsl:stylesheet>

Here, the main stylesheet overrides the product template.

But instead of reproducing the complete product transformation, it calls:

<xsl:apply-imports/>

The base stylesheet then generates the original product details.

The resulting structure is conceptually:

<article>
    <h1>Product Details</h1>

    <div>
        <h2>Tablet</h2>
        <p>Price: 30000</p>
    </div>
</article>

16. Advantages

The main advantages of <xsl:apply-imports> are:

  1. Code reuse
    Existing templates can be reused instead of rewritten.

  2. Reduced duplication
    Developers do not need to copy large templates into new stylesheets.

  3. Easy customization
    A project can modify selected parts of a common transformation.

  4. Better maintainability
    Changes to the base stylesheet can continue to benefit derived stylesheets.

  5. Modular design
    Transformation rules can be separated into reusable stylesheet modules.

  6. Layered transformations
    Different stylesheets can provide different levels of customization.


17. Limitations and Points to Remember

<xsl:apply-imports> should not be used simply as a replacement for <xsl:apply-templates>.

Its purpose is specifically related to imported stylesheets and import precedence.

You should remember these points:

  • <xsl:import> is used to import another stylesheet.

  • A template in the importing stylesheet can override a template in the imported stylesheet.

  • <xsl:apply-imports> allows the overriding template to invoke the lower-precedence imported template.

  • It helps extend existing templates without duplicating their implementation.

  • Import precedence determines which stylesheet's template is considered the overriding one.

  • <xsl:apply-imports> works on the current node.


Conclusion

<xsl:apply-imports> is an important XSLT instruction for building reusable and maintainable stylesheet architectures. It is especially valuable when a base stylesheet provides standard transformation rules and another stylesheet needs to customize those rules.

The key idea is simple: an overriding template can use <xsl:apply-imports> to invoke the original template from an imported stylesheet. This allows developers to add, modify, or extend transformation behavior while keeping the original implementation reusable.