XSLT - Conditional Compilation with use-when in XSLT 2.0 and 3.0

use-when is an XSLT feature used to conditionally include or exclude parts of an XSLT stylesheet before the stylesheet is actually compiled and executed. It is particularly useful when the same stylesheet needs to work with different XSLT processors, processor capabilities, or processing environments.

Unlike normal conditional instructions such as <xsl:if> and <xsl:choose>, which make decisions while a transformation is running, use-when operates during stylesheet preprocessing. The W3C specification describes this as conditional element inclusion. If the use-when expression evaluates to false, the element and its descendants are effectively removed from the stylesheet before normal stylesheet processing takes place. (W3C)

1. What is use-when?

The use-when attribute accepts an XPath expression that can be evaluated statically.

A simple example is:

<xsl:template match="/" use-when="system-property('xsl:version') >= 3.0">
    <result>
        <xsl:text>This template is available in XSLT 3.0.</xsl:text>
    </result>
</xsl:template>

Here, the processor evaluates:

system-property('xsl:version') >= 3.0

before the stylesheet is normally compiled.

If the expression evaluates to true, the template remains part of the stylesheet.

If it evaluates to false, the template is effectively excluded.

The important point is that this is not the same as executing an if statement during transformation. The stylesheet itself is being conditionally constructed before normal transformation processing begins. (W3C)

2. Why is use-when needed?

Suppose you want one stylesheet to support multiple environments.

For example, one processor may support schema-aware processing while another processor may not. You could have a stylesheet containing schema-related declarations that would cause problems on a processor without schema support.

With use-when, you can conditionally exclude those declarations.

For example:

<xsl:import-schema
    schema-location="book.xsd"
    use-when="system-property('xsl:is-schema-aware') = 'yes'"/>

If the processor is schema-aware, the declaration is included.

If the processor is not schema-aware, the declaration is excluded from the stylesheet.

This allows a single stylesheet to provide different implementations depending on processor capabilities. The W3C specification specifically identifies portability between schema-aware and non-schema-aware processors as a use case for use-when. (W3C)

3. use-when versus xsl:if

It is important to understand the difference between use-when and <xsl:if>.

An ordinary conditional instruction looks like this:

<xsl:if test="$price > 1000">
    <discount>Available</discount>
</xsl:if>

The condition depends on the source document or runtime data.

The transformation has already started when the condition is evaluated.

By contrast:

<xsl:template match="product"
              use-when="system-property('xsl:version') >= 3.0">
    ...
</xsl:template>

The condition is evaluated as part of stylesheet preprocessing.

Therefore:

Feature use-when xsl:if
Purpose Include/exclude stylesheet components Conditionally generate transformation results
Evaluation stage Stylesheet preprocessing Transformation
Access to source document No Yes
Access to runtime variables No Yes
Can remove an entire template Yes No
Mainly useful for Processor/environment-dependent stylesheet design Runtime business logic

This distinction is one of the most important concepts when learning use-when.

4. How use-when works internally

Consider:

<xsl:template match="customer"
              use-when="system-property('xsl:version') >= 3.0">
    <customer>
        <xsl:value-of select="name"/>
    </customer>
</xsl:template>

The processor first examines the use-when expression.

If it returns true, the processor retains the template.

Conceptually:

Stylesheet
    |
    v
Evaluate use-when
    |
    +---- true ----> Keep element
    |
    +---- false ---> Exclude element
                         |
                         v
                  Compile remaining stylesheet
                         |
                         v
                  Perform transformation

The excluded element behaves as though it was never present in the stylesheet. The XSLT 2.0 specification states that static or dynamic errors within an excluded element are not reported because the element is no longer part of the stylesheet, although XML parsing or validation errors can still occur. (W3C)

5. Using use-when with processor properties

One of the most useful applications is detecting processor characteristics.

XSLT provides the system-property() function for accessing processor-related properties.

For example:

<xsl:template
    match="/"
    use-when="system-property('xsl:version') = 3.0">

    <result>
        XSLT 3.0 implementation
    </result>

</xsl:template>

The expression checks the XSLT version supported by the processor.

Another example can check the processor vendor:

<xsl:template
    match="/"
    use-when="system-property('xsl:vendor') = 'Some Processor'">

    <result>
        Processor-specific implementation
    </result>

</xsl:template>

This can be useful when maintaining stylesheets that need to accommodate different processors.

However, processor-specific logic should be used carefully because excessive dependence on a particular processor can reduce stylesheet portability.

6. Conditional stylesheet modules

use-when can also be applied to <xsl:include> and <xsl:import>.

For example:

<xsl:include
    href="advanced-functions.xsl"
    use-when="system-property('xsl:version') >= 3.0"/>

Here, the module is included only when the condition is true.

You could provide different modules for different processors:

<xsl:include
    href="processor-a.xsl"
    use-when="system-property('xsl:vendor') = 'Processor A'"/>

<xsl:include
    href="processor-b.xsl"
    use-when="system-property('xsl:vendor') = 'Processor B'"/>

This technique allows the stylesheet architecture itself to change depending on the processing environment.

The W3C XSLT 2.0 specification gives a similar example involving different stylesheet modules selected according to the processor being used. (W3C)

7. Using use-when with templates

A template can be conditionally included.

Example:

<xsl:template match="employee"
              use-when="system-property('xsl:version') >= 3.0">

    <employee>
        <xsl:value-of select="name"/>
    </employee>

</xsl:template>

If the condition is false, the template does not participate in template matching.

This is different from writing:

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

In the second example, the template still exists. Only its output is conditional.

With use-when, the template itself can disappear from the stylesheet.

8. Conditional stylesheet declarations

use-when is not limited to templates.

It can be applied to many elements in the XSLT namespace.

For example:

<xsl:variable
    name="advanced-mode"
    select="true()"
    use-when="system-property('xsl:version') >= 3.0"/>

It can also be applied to literal result elements and other non-XSLT elements using the xsl: prefix:

<custom-output
    xsl:use-when="system-property('xsl:version') >= 3.0">
    Advanced processing
</custom-output>

The XSLT 3.0 specification states that an XSLT element can have use-when, while literal result elements and other non-XSLT elements can use xsl:use-when. (W3C)

9. Static expressions are important

The expression used by use-when must be suitable for static evaluation.

For example:

use-when="system-property('xsl:version') >= 3.0"

is appropriate because it depends on information available during stylesheet processing.

You should not think of use-when as a mechanism for examining the current XML input.

For example, this is conceptually inappropriate:

use-when="price > 1000"

The reason is that use-when does not operate with the normal source-document context used during transformation.

The specification places significant restrictions on the evaluation context specifically so that use-when can be evaluated early in stylesheet processing. (W3C)

10. use-when cannot replace normal conditional processing

Consider this requirement:

"Display a discount if the product price is greater than 1000."

You should use:

<xsl:if test="price > 1000">
    <discount>Available</discount>
</xsl:if>

You would not use use-when because the price belongs to the source document and is evaluated at transformation time.

use-when is better for requirements such as:

"Use this stylesheet component only when the processor supports XSLT 3.0."

That distinction can be summarized as:

use-when
    = Should this stylesheet component exist?

xsl:if / xsl:choose
    = What should this transformation produce?

11. Practical example: Different implementations

Suppose you want to provide a special template for XSLT 3.0 processors.

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

    <xsl:template
        match="/"
        use-when="system-property('xsl:version') >= 3.0">

        <result>
            <xsl:text>Using the XSLT 3.0 implementation</xsl:text>
        </result>

    </xsl:template>

</xsl:stylesheet>

When processed by a compatible XSLT 3.0 processor, the template is retained and can be used.

A more practical stylesheet might contain separate implementations:

<xsl:template
    match="/"
    use-when="system-property('xsl:version') >= 3.0">

    <result>
        <xsl:text>Advanced implementation</xsl:text>
    </result>

</xsl:template>

<xsl:template match="/">
    <result>
        <xsl:text>General implementation</xsl:text>
    </result>
</xsl:template>

The first template is conditionally available, while the second provides a general implementation.

12. Using use-when for portability

Portability is one of the strongest reasons to learn this feature.

Imagine that an organization uses multiple XSLT processors. One processor supports a particular advanced capability while another does not.

Instead of maintaining completely separate stylesheet files, you can conditionally include the relevant stylesheet components.

For example:

<xsl:template
    match="document"
    use-when="system-property('xsl:is-schema-aware') = 'yes'">

    <validated-document>
        <xsl:apply-templates/>
    </validated-document>

</xsl:template>

A non-schema-aware processor can exclude this template.

This allows the rest of the stylesheet to remain usable.

The W3C specification explicitly documents this kind of conditional exclusion as a portability technique. (W3C)

13. Advantages of use-when

The major advantages are:

Early decision making

The decision happens before normal transformation processing.

Better portability

A stylesheet can adapt to different processor capabilities.

Avoiding unsupported constructs

Unsupported declarations can be excluded before they cause stylesheet-processing problems.

Modular stylesheet design

Different stylesheet modules can be selected according to environmental conditions.

Cleaner architecture

Instead of filling a stylesheet with runtime conditions for processor-dependent features, you can remove unnecessary components altogether.

Useful for version-dependent development

Different stylesheet implementations can be selected depending on the XSLT processor version.

14. Limitations of use-when

use-when also has important limitations.

First, it is not designed for normal source-data conditions.

This is wrong conceptually:

use-when="customer/status = 'active'"

because the condition depends on transformation input.

Second, the expression must be statically evaluable.

Third, the evaluation context is deliberately restricted. The processor does not provide the normal source-document context that you have during transformation. (W3C)

Fourth, use-when should not be overused. If the condition is simply a business rule involving XML data, normal XSLT conditional processing is more appropriate.

15. Difference between use-when and xsl:fallback

These features can sometimes appear together, but they solve different problems.

use-when decides whether a stylesheet component should be included.

xsl:fallback provides fallback behavior when an XSLT processor encounters an instruction it does not understand under forwards-compatible processing.

For example, XSLT's forwards-compatible processing rules are designed to allow stylesheets to use features from later versions while defining fallback behavior where appropriate. (W3C)

Therefore:

use-when
    -> conditionally include/exclude stylesheet components

xsl:fallback
    -> provide fallback behavior for unsupported instructions

They can complement each other, but they are not interchangeable.

16. Important point about errors

One particularly useful property of use-when is that an excluded stylesheet element is treated as though it were not present.

For example:

<xsl:template
    match="/"
    use-when="false()">

    <xsl:unknown-instruction/>

</xsl:template>

Because the template is excluded, the processor does not normally process the contents of that excluded template as part of the stylesheet.

The XSLT 2.0 specification explains that static and dynamic errors associated with an excluded element and its contents are not reported, apart from errors associated with the use-when expression itself. XML parsing and validation errors are an exception because the XML must still be syntactically valid. (W3C)

This behavior is one reason use-when is useful for compatibility-oriented stylesheet development.

17. A complete example

Consider the following stylesheet:

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

    <xsl:output method="xml" indent="yes"/>

    <xsl:template
        match="/"
        use-when="system-property('xsl:version') >= 3.0">

        <result>
            <xsl:text>This implementation requires XSLT 3.0.</xsl:text>
        </result>

    </xsl:template>

</xsl:stylesheet>

The processing sequence is approximately:

1. Read stylesheet
       |
       v
2. Evaluate use-when
       |
       v
3. Check XSLT processor version
       |
       +---- Condition true
       |          |
       |          v
       |    Keep the template
       |
       +---- Condition false
                  |
                  v
            Exclude the template

This is fundamentally different from checking a value from the source XML.

18. Best practices

When using use-when, follow these practices:

  1. Use it primarily for stylesheet-level decisions, not business rules.

  2. Keep the expression simple and statically evaluable.

  3. Use processor properties when you need processor or capability detection.

  4. Use it carefully when supporting multiple XSLT versions.

  5. Prefer modular stylesheets when different implementations become large.

  6. Do not use use-when simply because an ordinary <xsl:if> exists.

  7. Clearly document why a stylesheet component is conditionally included.

  8. Test the stylesheet with every processor or XSLT version that you intend to support.

19. Summary

use-when is an XSLT feature for conditional inclusion and exclusion of stylesheet components during stylesheet preprocessing. It was introduced in XSLT 2.0 and remains available in XSLT 3.0. (W3C)

Its most important characteristic is that it works before the normal transformation takes place. This makes it different from <xsl:if> and <xsl:choose>, which make decisions while processing the source document.

The feature is particularly useful for creating portable, version-aware, and processor-aware XSLT stylesheets. It can conditionally control templates, declarations, stylesheet modules, and other stylesheet components based on statically available information.

The simplest way to remember the concept is:

xsl:if
    -> conditionally produce output

use-when
    -> conditionally include stylesheet code

That distinction makes use-when especially valuable when developing advanced XSLT 2.0 and XSLT 3.0 applications.