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:
-
Use it primarily for stylesheet-level decisions, not business rules.
-
Keep the expression simple and statically evaluable.
-
Use processor properties when you need processor or capability detection.
-
Use it carefully when supporting multiple XSLT versions.
-
Prefer modular stylesheets when different implementations become large.
-
Do not use
use-whensimply because an ordinary<xsl:if>exists. -
Clearly document why a stylesheet component is conditionally included.
-
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.