XSLT 2.0, the latest specification released by the World Wide Web Consortium (W3C), is a language for transforming XML documents. It includes numerous new features, with some specifically designed to address shortcomings in XSLT 1.0. In this collection of articles, you'll get a high level overview and an in-depth look at XSLT 2.0 from the point of view of an XSLT 1.0 user who wants to fix old problems, learn new techniques, and discover what to look out for. Examples derived from common applications and practical suggestions are provided if you wish to upgrade. To help you begin to use XSLT 2.0, migration techniques will be provided.
One stylesheet can be executed by several processors
This article will present details of all the XSLT constructs available for mixing version 1.0 and 2.0 features, which are needed for most upgrading tactics discussed in Part 2 of this series. (See the Resources section for links to prior parts.) In essence, this is a toolkit for you to make your stylesheets portable, by giving them ways to cope with unknown features. Many of the techniques also apply to portability of a stylesheet between XSLT processors that support different extensions.
XSLT 2.0 expands upon XSLT 1.0 in several ways: new elements, new attributes on old elements, new XPath operators, new functions, and new datatypes. The 1.0 processor would not recognize the new constructs and would raise errors unless you use the tools described here to overcome the errors. A 1.0 processor can accept a 2.0 stylesheet because the namespace URI (Universal Resource Identifier) for XSLT elements has not changed for 2.0; only the (mandatory) version number has changed. In other words, the elements of XSLT 1.0 and 2.0 are commingled, but the 2.0 set is larger. When Forwards Compatibility (FC) is in effect, the processor must assume that XSLT element names it does not recognize might be legitimate for a future version, and it must ignore such elements, except as noted in this article. This principle holds for both 1.0 and 2.0 processors.
When a stylesheet processor encounters an unrecognizable function, operator, attribute, or element in the XSLT namespace, the result can either be an error, to ignore the construct, or to execute an alternative path. The error is often the default, even though it is the least desirable if your goal is portability. If the construct is legal syntax in one version, but unsupported in an older (or newer) version, the desirable outcome is often to choose an alternative path that makes sense and accomplishes the nearest equivalent effect. Where the default outcome is an error, the stylesheet writer will have to be aware of the differences in XSLT versions, and future-proof and/or past-proof the stylesheet (especially when he or she does not know up front which version of XSLT processor performs the transformation). The toolkit available to the stylesheet writer in XSLT 2.0 to future-proof or past-proof a stylesheet consists of:
- Backwards or Forwards Compatibility mode, triggered by the
versionstandard attribute xsl:fallback- The
use-whenstandard attribute - Conditional instructions
xsl:chooseandxsl:if function-available(),element-available(), andsystem-property()functions
Of these, all but use-when existed in 1.0,
but most have been slightly altered for 2.0, and the version attribute has been greatly expanded.
The applicability of conditionals has been curtailed for version 2.0 (and presumably for future versions, should there be
any). Before reading about the toolkit, you should know a couple concepts that are new in the XSLT 2.0 specs: static error checking and standard attributes.
Scanning for stylesheet errors
After a processor consolidates a stylesheet from all the imported and included modules, it goes through various steps to prepare for transformation. One such step is to scan for static errors, which are situations that will always be erroneous regardless of the transformation input. Included among the static error conditions are unknown XSLT elements, attributes, and functions. Another kind of static error is where the element or attribute is recognized, but has been placed where it is not allowed. Each tool in the toolkit takes effect either before or after the static error checking phase, and the ramifications are covered in this article.
Standard attributes and scoping
If you understand the scoping of XML namespaces, then you would readily understand the scoping used in stylesheets. (If not,
scoping is defined after Table 1.) In XSLT 1.0, a limited form of scoping was used for
extension-element-prefixes and exclude-result-prefixes, and now those attributes
have been joined by several others
in a new classification called Standard Attributes.
In XSLT 1.0, most but not all elements could take attributes, which were always specified anew for each element
on which they appeared. XSLT 2.0 defines a collection of standard attributes, and these attributes can appear on any
element, including elements like xsl:choose that otherwise take no attributes. Standard attributes also take effect on
Literal Result Elements (LREs; see the notes about LREs for more explanation),
in which case the name is qualified to the XSLT namespace. For example, the version attribute can appear on an XSLT
element, and xsl:version can appear on LREs. (The prefix is needed because non-namespaced
attributes on LREs are Literal Result Attributes that propagate to the result.) There are also some attributes in the
xml namespace (xml:lang, xml:space, xml:id, xml:base),
which can appear on any XSLT element. Some of these attributes affect the results of a transformation. If they are defined on an LRE, then they
are copied to the result tree.
Table 1. Standard attributes
| Name | Brief Description | Effect of nesting |
|---|---|---|
| Collation to use when none specified in instruction or function | override |
| Suppresses namespace declarations (nodes) in output | cumulative |
| In a sequence constructor, designates namespaces for elements that are to be treated as extension instructions rather than Literal Result Elements (LREs). See the notes about instructions for more information. | cumulative |
| Allows an element to be included or excluded from the stylesheet. This article includes a full discussion of how to use it. | The first one whose condition is false excludes all inner content. As long as the conditions are true, nesting continues. |
| Sets the XSLT version of the stylesheet, module, or a sub-tree. | override |
| Sets the namespace assumed for unprefixed elements in an XPath expression. | override |
This article discusses version and use-when, and mentions
extension-element-prefixes. The term instruction is one of a handful of XSLT constructs explained
in the structure table (Table 2).
When an XSLT element defines a standard attribute, the effects of the standard attribute are applied to its descendent elements unless the
descendent element defines the same standard attribute with a different value. Thus, for any given element on a stylesheet that does not define the standard attribute
on itself, it inherits the standard attributes from its closest ancestor element that defines them. The scoping of these attributes is determined statically. That means a
descendent element only inherits the standard attribute if it is defined on the same stylesheet module, according to the XML structure of the document, rather than
the structure of how an XSLT processor would execute the stylesheet elements. For example, if there are two templates defined in a stylesheet module, where
one template contains an xsl:call-template with an attribute version="1.0", the other named template,
when called, is not affected by the attribute version="1.0". The
reason is that the scoping of the attribute version="1.0" only applies to the xsl:call-template
element and its own descendants (for example, xsl:with-param). It does not affect the named template that is called because that
template, from the point of view of the XML document, is not a descendent of the xsl:call-template element. Thus, the named
template's xsl:template must also set
an attribute version="1.0" in order to process this template in backwards compatibility mode.
The Toolkit for Mixing Versions
Future-proofing is often like extension-proofing, so you can use a lot of the tools below to enhance portability of stylesheets against various differences, not just versions. The similarity is that both provide a way to cope with unknown elements and functions; the difference is that for future-proofing, the unknowns are in the XSLT namespace.
Broader uses for the version attribute
Backwards compatibility (BC) and FC modes are always triggered by the version attribute, not by any processor switch or launch-time option.
A 2.0 processor might support the Backwards Compatibility (BC) feature module, at the vendor's option, in which case the
stylesheet can have version="1.0" and it will not result in an error.
In addition to its familiar place on xsl:stylesheet, that attribute is recognized by a 2.0 processor on inner elements,
as described in the section on scoping standard attributes.
BC mode is in effect when the element has a version number, either due to its own version
attribute or through scoping, that is lower than the version of the processor.
All XSLT processors, including 1.0 processors, are required to support Forwards Compatibility (FC), which is where the version number on the stylesheet is higher than the version of the processor. When FC is in effect on a stylesheet, the processor must ignore unknown XSLT declaration elements and perform fallback on any unknown XSLT instruction elements, when fallback actions have been specified. (The distinction between instructions and declarations is explained in the structure table.)
In XML, attributes with unqualified names are typically presumed to be meaningful to the element containing them, and
XSLT follows that practice. An unknown non-namespace-qualified attribute on an XSLT element raises an error, unless FC mode is in effect.
In XSLT 2.0, there are 16 elements that have new attributes they didn't have in 1.0, not counting the
standard attributes that can be anywhere.
Fortunately, in no case did an attribute that was optional in 1.0 became mandatory in 2.0, nor are any brand new attributes now mandatory on old instructions.
Note, however, that in a few cases, an instruction that existed in 1.0 was expanded for 2.0 in a way other
than through its attributes. In particular, xsl:apply-imports, xsl:key, xsl:sort, and
xsl:value-of had no children under 1.0 but do under 2.0, while xsl:param
has new parent elements, and it can be required to have no children, depending on its parent.
The transformation logic controlled by XSLT elements in FC or BC mode can differ from the same elements outside of those modes. XSLT 1.0 and 2.0 specifications (see Resources for links) describe the differences and how to use them. As a general rule, BC only has an effect on an XSLT element where it is specifically documented in the 2.0 family of specs.
Remember that xsl:output/@version is different. It sets the version number of the output document markup, such as
the XML version for XML output. The next article in this series will include an example for how to deal with
xsl:output.
When an XSLT 1.0 or 2.0 processor, executing in FC mode, encounters an instruction in the XSLT
namespace where it is not permitted, it should throw an error unless this element has at least one xsl:fallback
child element. The presence of xsl:fallback indicates to the processor that rather than
throwing an error, it should execute the sequence constructor (set of instructions) in the
xsl:fallback instruction
and continue processing. This future-proofing mechanism for XSLT instructions is available when the containing element either specifically
allows xsl:fallback or has a sequence constructor. A simple example is when a 1.0 processor executes a 2.0
stylesheet template and encounters an xsl:document instruction. The 1.0 processor simply ignores all children
except the xsl:fallback elements and executes those in order. If the 2.0 instruction specifically allows xsl:fallback
but does not have a sequence constructor, such as the xsl:analyze-string instruction, the 1.0 processor also
ignores xsl:matching-substring and xsl:non-matching-substring (the only permissible children),
and executes the sequence constructor in the xsl:fallback element. (The only difference is that the
xsl:fallback elements have to be the last children relative to xsl:matching-substring and
xsl:non-matching-substring to avoid a static error when executed by a
2.0 processor, even though a 1.0 processor does not care about the ordering of xsl:fallback relative to its siblings.) If an xsl:function element
has an xsl:fallback instruction, then an XSLT 1.0 processor ignores the xsl:function element
entirely and does not execute its xsl:fallback. That is because the fallback mechanism only works for instruction elements, not
declarations. (See the structure table and the following remarks for details about "instruction" and "declaration" elements in XSLT.)
Note that the text about when the fallback mechanism is applied in the XSLT 2.0 spec is refined compared to the XSLT 1.0 spec. A scenario
where this change makes a difference is
when the stylesheet writer wishes to pass an xsl:with-param value within xsl:apply-imports
in those cases where the stylesheet is processed by a 2.0 processor, and rely on the default value of the template parameter
if the processor is 1.0. (Note that 1.0 did not allow xsl:with-param inside xsl:apply-imports.)
Theoretically, one could accomplish this by adding an emptyxsl:fallback child in the
xsl:with-param element to avoid an error in 1.0. This is permissible because
the fallback mechanism applies when
"it is an element in a template and XSLT 1.0 does not allow such elements to occur in templates" according to the
XSLT 1.0 specification.
In XSLT 2.0 however, the fallback mechanism applies where "an element in the XSLT namespace appears as part of a sequence constructor." Since the
xsl:with-param is not part of a sequence constructor of xsl:apply-imports, the fallback
mechanism is not applicable.
The text in XSLT 2.0 might seem irrelevant for this particular example, since a 1.0 processor naturally
implements the FC behavior as dictated by the XSLT 1.0 specification. In reality, this might not be the case. Since XSLT 2.0
will be the first recommendation since XSLT 1.0, many existing implementations of XSLT 1.0 did not have the need to
implement FC until the 2.0 specification became more commonly used. Thus, this feature might be unsupported or partially supported.
When the time comes to implement this feature, the implementor can choose to support the fallback mechanism only where its use is more
obvious, such as within new 2.0 instructions (such as xsl:document or xsl:analyze-string)
and postpone implementing xsl:fallback in less apparent constructs like within
xsl:with-param. Thus, for this particular scenario, the stylesheet writer should avoid
using xsl:fallback inside xsl:with-param, and instead apply
xsl:choose to choose between xsl:apply-imports with and without xsl:with-param
depending on the processor version. (The system-property function is used to
check the processor version.)
The xsl:fallback instruction will perform as expected for the following new-for-2.0 instructions:
xsl:analyze-string, xsl:document, xsl:for-each-group, xsl:namespace, xsl:next-match,
xsl:perform-sort, xsl:result-document, and xsl:sequence. All are instructions and many also
contain a sequence constructor, which is a collection of instructions.
Since xsl:fallback offers general protection against
unknown instructions, it works in extension instructions, and does not require FC mode for falling back on instruction elements
that are not in the XSLT namespace. (There is the possibility of nested
xsl:fallback elements, where you guard against a 2.0 instruction and an extension instruction.)
It is worth noting, though, that xsl:fallback only applies
to one instruction at a time. Therefore, the xsl:fallback element should contain whatever is needed to substitute for the
single instruction that contains it.
The use-when attribute and element filtering
The attribute use-when is a new 2.0 standard attribute that can be
set on any XSLT element. The attribute
value is an XPath expression that results in a boolean after evaluation. If the result is false, then the processor excludes the element and its descendants in the stylesheet. This is a very useful tool that allows the stylesheet
writer to exclude completely certain elements, templates, or entire stylesheet modules from the transformation if an XPath
condition is not met. For those processors that have an explicit compile phase, use-when
filtering is intended to avoid compiling blocks of code that the processor couldn't execute. Since this attribute is meant
to be evaluated at the start of the static analysis phase (before
scanning for static errors and before an input
source document is needed), there are restrictions on the context information exposed to the processor when evaluating the
XPath expression. For example, a variable reference in the expression results in an error even though the element is
positioned in a template where the variable is in scope.
Some key differences are:
- Can't use or detect types defined in an imported schema
- Can't check the availability of stylesheet functions, but you can check for vendor-written extension functions built into the processor
- Can't make references to any variables or params, even if seemingly in scope
- Can't check the availability of documents, text files, and collections
- Can't rely on BC mode when evaluating the expression
Refer to part 3.12 of the XSLT 2.0 specification (see Resources) for a complete list of context
information exposed during use-when attribute evaluation, but note that the
system-property() and availability functions discussed below are
available to use. A use-when test can also help you
choose collations, as long as it includes an expression that will tell you which collations are available. One possibility
is to use the processor identification, as discussed under the system-property function.
The use-when attribute can be used for forwards and backwards compatibility processing. The drawback is
that a 1.0 processor would not understand this attribute, and would throw an error if the stylesheet has attribute
version = "1.0" (that is, not processed in FC mode). To write a stylesheet that will work with 1.0, 2.0,
and a future version, then you can combine conditional and use-when to avoid static errors no matter which version
of processor you are using. The next article in this series will show how to deal with these limitations.
Caution: User-defined Data Elements (UDDEs) are not required to support use-when; the
vendor can choose whether to support it on UDDEs and extension instructions. (These elements are described in the
structure table in this article.) If you need to exclude a UDDE and the vendor indicates that
use-when on UDDEs is not supported, rather than just have it be ignored, you can put the UDDE in an included
stylesheet module, and put the @use-when on the xsl:include. If
you need to exclude an extension instruction, the safest approach is to have alternative templates and apply
@use-when filtering at the template level.
Conditional branching in 1.0 and 2.0
The conditional instructions xsl:if and xsl:choose have the advantage
over @use-when that these constructs existed in XSLT 1.0. Thus, they can
be used for excluding code for version 1.0, rather than version 2.0 or greater, where the
use-when attribute is employed.
Using the use-when attribute to filter constructs has the benefit that if the constructs within might result in an error (because the current processor's version does not support that construct), then the error must never occur because use-when filtering happens before the scan for static errors.
A downside of @use-when is that certain context information is not available to the XPath expression
inside @use-when but is available for @test in xsl:when.
However, 2.0 processors must throw an error for any invalid content (other than unknown extension functions in certain situations) in a sequence constructor, even if the content is supposedly guarded by an xsl:choose that tests an appropriate boolean value.
If that policy were to continue into higher versions, your stylesheets might have problems with obsolete guarding code. In 2.0, xsl:choose can only avoid raising errors when
all branches have no static error.
For a 2.0 processor, the only potential invalid content in a
1.0-legacy stylesheet is either a syntactic oddity or, in some situations, the rarely-used namespace axis. (See
Part 3 of this series for more about support of the namespace axis.) The conditionals are
instructions and therefore you can only place them in sequence constructors, while
use-when is a standard attribute that can go on any XSLT element, including the ones that
are not instructions.
For illustration, here are three ways to determine if a processor implements the 1.0 or 2.0 specification
as a boolean value for either the
use-when attribute or conditional elements (xsl:if and xsl:choose).
system-property('xsl:version') = '2.0'returns true for a 2.0 processor and is normally the preferred form, for readability.function-available('unparsed-text')returns true for a 2.0 (and later) processorelement-available('xsl:for-each-group')returns true for a 2.0 (and later) processor
You can use the latter two where the one function or element given as the argument is the only feature in the code block that might not be supported.
As with 1.0, the set of functions in XSLT 2.0 is extensible. You can supplement the mandatory set of built-in functions in several ways, and use function-available() to verify the availability
of functions from any source, including built-in ones. XSLT 2.0 requires support for all the functions in
the F&O spec (see Resources), just as XSLT 1.0 required support for all the XPath 1.0 functions, and XSLT
adds in its own functions in each version. The
XSLT-only functions for 2.0 are: current-group, current-grouping-key, regex-group, document, unparsed-text,
unparsed-text-available, key, format-number, format-dateTime, format-date, format-time, current, unparsed-entity-uri,
unparsed-entity-public-id, generate-id, system-property, function-available, type-available, and
element-available.
The signature and utility of the function-available function has changed in XSLT 2.0. You can still
use this function in an expression to determine
if a particular built-in or extension function is supported as the stylesheet element is being processed. In XSLT 2.0, you can use a second argument to further check if a particular function that supports a specific number of arguments, or arity, is supported. The utility of this function has also expanded and contracted at the same time. It has expanded in a sense that it can detect a greater variety of in-scope functions, whether used within a
use-when attribute or not. It can always detect if a built-in function is supported, defined from both the
F&O and XSLT 2.0 specifications. Vendor-provided extension functions should always be reported as available in that vendor's
processor (the node-set
function for 1.0 is an example). It can also detect if a constructor function of a schema-type is supported; more about that in a moment.
Finally, if used outside of the use-when attribute, it can also detect if a user-defined stylesheet function is supported.
(See Part 1 of this series
for more about stylesheet functions.)
Though these expansions are useful, the application of function-available()
has contracted at the same time.
When a stylesheet processor analyses a stylesheet for static errors, it will look for syntaxes that it does not understand. If an element is
not processed in BC mode and not guarded by a suitable use-when attribute, then the processor throws a static error if it
finds a function that it does not understand in an XPath expression. For example, in your sequence constructor within a template, you want to
add an xsl:choose to check if an extension function is supported using function-available().
If it is not supported, then you define the alternate behavior in the xsl:otherwise.
This is a typical scenario of how function-available is used in XSLT 1.0. Unfortunately, unless the extension
function is always supported (which defeats the purpose of checking for it in the first place), the evaluation of this stylesheet by a 2.0 processor
during static-error checking results in an error if the extension function is not supported. To get around this problem in 2.0, use the
use-when attribute instead of xsl:choose.
That is because the evaluation of the use-when
attribute occurs before static-error checking. Thus, it is not recommended to use
function-available() with xsl:choose and
xsl:if unless it is in BC mode.
Since a function call is usually just a part of an XPath expression, an unknown
function causes the execution of the entire XPath expression to fail.
Furthermore, XPath expressions always occur as attribute values, so the scope of any exclusion is the element
containing the attribute in question.
Unknown functions are not guarded by FC mode; they require explicit guards against their inadvertent execution.
Thus, checking function-available() must occur
outside of the attribute that holds the XPath expression (rather than using an IfExpr) and should be used in conjunction
with @use-when for future
proofing, or a combination of xsl:choose and @use-when for future and
past-proofing. The next installment in this series will include an example of that combination.
A 2.0 processor with Schema Awareness can also handle user-defined datatypes, including constructor functions
for those datatypes that are atomic and derived from primitive datatypes. This is new to XSLT 2.0 and using the new
type-available() function will accomplish the same task as checking availability of the constructor function.
For example, if you used xsl:import-schema to make the processor aware of your my:envelope-number datatype, derived from the
known xs:decimal datatype, then XPath expressions in that stylesheet can use
my:envelope-number(decimal)
as an additional available function. The type-available() function can test whether a
particular datatype definition has been loaded into the context,
whether or not that type has a constructor function. Do not use this function with use-when because the type definitions haven't been imported yet. Continuing the example, neither function-available('my:envelope-number') nor
type-available('my:envelope-number') will work with use-when.
You can use function-available() with use-when filtering (for 2.0 and forward), though that might
be better for extension functions than for testing functions built in to XSLT and XPath.
Use it for a single built-in if that makes the code readable. Namespace-qualified names of functions always signal an
extension function in 1.0, at least according to the
1.0 spec. It is not clear whether all implementers of 1.0 processors noticed this, but it has interesting uses for
stylesheets that will be run by both 1.0 and 2.0 processors.
The element-available() function has remained unchanged from 1.0 to 2.0. It is only about "instructions" (defined in the
structure table). Likely uses are in @use-when or
in xsl:choose if the other branch is not a static error. Reminder: To work around a single instruction that might be unknown, the
fallback mechanism is safer, because both 1.0 and 2.0 specs agree that the element in question must not raise a static error as long
as FC mode is in effect. Bonus: You don't need to bother with element-available(), because that is essentially the only condition
xsl:fallback ever uses as a criterion.
This article discusses the xsl:version keyword, one of several available in the
system-property function. New for 2.0, this function can also test for all three optional feature
modules described in Part 3 of this series: Schema Awareness, Backwards Compatibility, and Serialization. Another property that
might be interesting is xsl:product-name, which can exclude large amounts of code based on which vendor's
processor is running.
In use-when tests, the system-property() function is usually the best function
to use, because its test is readable. The use-when filtering occurs early in the setup of a transformation,
specifically before any input document is loaded or any launch options are acted upon.
(See Part 3 for an explanation of launch options.)
The system-property() function reports directly on the capabilities of the processor.
In the ideal world, a stylesheet is portable across processors yet able to exploit vendor-specific extensions and optimizations when run by a given vendor's processor. This is accomplished through namespaces. (See Resources to learn more about XML namespaces.) Several vendors might choose to implement a shared extension package such as EXSLT, in its own namespace, as well as their own extensions. Thus a processor might recognize several namespaces as designating elements (or attributes or functions) that it knows. Other foreign declarations and attributes must be ignored. Foreign instructions would raise an error if actually invoked, but you can guard against unwanted invocation using techniques described in this article. Given all these policies about treatment of unknown elements, Forwards Compatibility simply emerges as a special case that is accorded the same treatment.
The Working Group is strongly suggesting that @use-when is the
way to make your stylesheets adaptable and configured appropriately for different platforms. It can adapt to anything that
system-property() or
function-available() tells you, it can exclude any element, and its exclusions happen at an
early stage of processing.
You have now seen all the functions, instructions, and attributes that are used for compatibility across XSLT versions. This toolkit is slightly larger than the toolkit for portability across different implementations of the same XSLT version from different vendors. If you want to use 2.0 features and haven't started to look at your existing stylesheets and how they must change, this article provides some ideas about new code replacing old at different granularities. You might replace an XPath expression, an instruction, a template, or an imported stylesheet module, among other constructs, and the replacement might be a different granularity. For example, a new 2.0 function might allow a template with several expressions and instructions to collapse down to a single XPath 2.0 expression. The next article in this series will provide examples of the portability techniques in use. Together with this article, you will get a sense of the hands-on work that is needed to take advantage of the new features.
Appendix: Structure of a stylesheet
This article uses terms such as instructions, declarations, and extension elements to classify the elements and attributes of a stylesheet more precisely. These terms are needed to express the constraints on each item in the portability toolkit.
Categories of elements in a stylesheet
The XSLT 2.0 document issued by the W3C (see Resources) specifies 49 elements in the XSLT namespace, including 14 new ones, and provides guidance about non-XSLT elements that might be present. The XSLT processor that executes a stylesheet must recognize and enforce the XSLT namespace, and it can also recognize elements from other namespaces as meaningful. To ease the discussion of the roles of various elements that can appear in a stylesheet, they are classified by the depth at which they first appear.
Table 2. Structure of a stylesheet
| Level | XSLT elements (some appear at more than one level) | non-XSLT elements |
|---|---|---|
0 |
| A non-XSLT element in an XML document can contain XSLT elements. This is the realm of the "embedded stylesheet" and outside the scope of this article. |
1 | Classic declarations that do not directly contain instructions and are used in the setup stages: Definition-type declarations that can contain instructions: | User-Defined Data Element (UDDE) or extension declaration (processor decides, based on namespace) Note: Elements whose name is not namespace-qualified raise an error. |
2 | Instructions: | Literal Result Element (LRE), unless its namespace has been declared to be an extension namespace, in which case it is an extension instruction. |
subsidiary | Subsidiaries to specific instructions: Subsidiaries to declarations: | Treatment of non-XSLT elements depends on the constraints of the containing element. For example, |
Notes about Declarations and UDDEs
The elements at level 1 were called top-level elements in the XSLT 1.0 document. The ones in the XSLT namespace are called declarations in the XSLT 2.0 document. Other namespace-qualified elements at level 1 of the stylesheet are called user-defined data elements (UDDEs) in the XSLT 2.0 document. Fallback does not work on declarations or UDDEs.
UDDEs must be ignored if not recognized by the processor. A processor might recognize UDDEs in its own namespace
for various uses; the XSLT 1.0 spec suggested optimization hints, information about handling inputs and outputs, structured
documentation of the stylesheet, and declarations associated with extension elements or functions from the same namespace.
The 1.0 spec overlooked the potential of foreign elements belonging to the stylesheet writer rather than the processor vendor and
being used for in-stylesheet data, especially a table for xsl:key. The new name (UDDE) suggests that the
XSL Working Group now recognizes data storage as the most likely use.
UDDEs may support the standard attributes or allow XSLT instructions as children,
at the discretion of the vendor implementing the processor.
In any case, UDDEs must not alter conformant processing.
When a vendor implements the Schema Awareness feature module (see Parts 1 and 3 of this series), the XSLT
processor will accept the xsl:import-schema declaration. This element is different from the others; instead of XSLT elements, it has elements of the XML Schema vocabulary as its (optional) children.
Notes about Instructions and LREs
The elements at level 2 are called instructions in both versions of XSLT. Level 2 is also where Literal Result
Elements (LREs) occur, which are elements that are to be replicated in the result rather than serving as instructions
to the processor. The 2.0 spec has
a formal definition of instruction and of the sequence constructor that comprises a series of instructions and LREs.
(Sequence constructors can also contain character data, either between elements or alone.)
Some XSLT elements contain a sequence constructor, as can an LRE.
The sequence constructors of some XSLT elements are restricted; for example, the
sequence constructor of xsl:comment cannot contain any instructions that would cause the comment content to be
anything other than text.
The extension-element-prefixesstandard attribute is significant for all prefixes, even
for ones not recognized by the processor currently executing the stylesheet (that is, other vendors' extensions).
It separates LREs from foreign elements that should be treated as instructions rather than LREs. While a processor does not need
extension-element-prefixes to recognize
extension attributes, UDDEs serving as extension declarations, and extension functions,
it is always a good idea to make the explicit statement, and it will also suppress the creation of a namespace
declaration for that prefix in the result document.
Extension instructions can support the standard attributes or allow XSLT instructions as children,
at the discretion of the vendor implementing the processor. Even support for @use-when is
discretionary.
Extension instructions must allow xsl:fallback as a child element.
The last row of the structure table (Table 2) lists those elements that occur as subsidiaries to particular instruction or declaration
elements. The Working Group that wrote the specs has not bothered to provide a term for these. Some, like xsl:when, are only
permitted as a child of one specific element. All subsidiaries can contain a sequence constructor except
xsl:output-character and xsl:param when it is a subsidiary of
xsl:function.
In both 1.0 and 2.0, non-namespaced attributes that appear on an XSLT element, other than the specified ones, cause an error
unless FC mode is in effect. This is especially significant for use-when, which was unknown
in 1.0 and is a standard attribute in 2.0. Since XSLT stylesheets are XML documents, XSLT
elements are also allowed to have attributes in the xml
and xmlns namespaces.
An attribute from another namespace can appear on an XSLT element; it is ignored unless its namespace is treated by
the processor as an extension namespace and the vendor has ascribed a particular significance to that attribute, in
which case it is an extension attribute (now an
official term in the specs). In 1.0, extension attributes were often used in xsl:output to
provide extra control over serialization. There is no requirement to declare explicitly that attributes in a particular namespace
are extension attributes, which is why XSLT is so tolerant of attributes it doesn't recognize.
A namespaced attribute on an LRE must always be copied through to the result, except for those in the XSLT namespace. If the attribute is recognized by the processor as an extension attribute that the processor implements, then the attribute may affect the behavior of the processor (within limits) as well as being copied.
Non-XSLT constructs found in a stylesheet
The structure table shows how the processor must handle foreign elements at each level. XSLT is extensible, and it has been designed to tolerate foreign attributes on any element. On the other hand, an XSLT processor is not allowed to recognize extension points in any comment or text node of the stylesheet. The XML namespaces mechanism (see Resources for links) is used to keep one processor's extension elements, attributes, and functions separate from those of another processor, as well as from the official XSLT constructs.
Learn
- The W3C site: Visit this great source of information on standards such as:
- XSLT 1.0
- XSLT 2.0
- XSLT 2.0 Requirements
- XPath
- XPath 2.0
- Functions and Operators (F&O)
- Data Model (XDM)
- Formal Semantics
- Serialization
- XQuery
- XML Schema
- XML 1.1
- XHTML
- Namespaces in XML
- IBM XML certification: Find out how you can become an IBM-Certified Developer in XML and related technologies.
- XML technical library: See the developerWorks XML Zone for a wide range of technical articles and tips, tutorials, standards, and IBM Redbooks.
- developerWorks technical events and webcasts: Stay current with technology in these sessions.
-
"Plan to Use XML Namespaces" (David Marston, developerWorks, Nov 2002, with April 2005 updates): Read about the purpose of namespaces and how to use namespace-qualified names ("QNames") in XPath expressions.
-
"Improvements in XSLT" (David Marston and Joanne Tong, developerWorks, October 2006): In the first part of this series, discover which XSLT 2.0 features are likely to motivate an upgrade. You'll also find some material about XPath 2.0 features.
-
"Five strategies for changing from XSLT 1.0 to 2.0" (David Marston and Joanne Tong, developerWorks, November 2006): Read the second part of this series, which describes the higher-level decision factors for planning an upgrade to XSLT 2.0, setting the stage to use Backwards and Forwards Compatibility as transition tools.
-
"Why the transition from 1.0 to 2.0 needs planning" (David Marston and Joanne Tong, developerWorks, November 2006): In the third part of this series, peruse a buyer's guide to XSLT 2.0 processors.
- "Make your stylesheets work with any processor version" (David Marston and Joanne Tong, developerWorks, February 2007): Read the fifth part of this series which shows how to write a stylesheet that is portable between XSLT 1.0 and 2.0.
Get products and technologies
- IBM trial software: Build your next development project with trial software available for download directly from developerWorks.
Discuss
- XML zone discussion forums: Participate in any of several XML-centered forums.
- developerWorks blogs: Get involved in the developerWorks community.
David Marston has worked with XML technologies since late 1998, particularly on standards conformance. Over his 25+ years in the computing business, he has been involved with all aspects of software development. He is a graduate of Dartmouth College and a member of the ACM. He is on the Next-Generation Web team at IBM Research. You can contact him at David_Marston@us.ibm.com.