xsl:stylesheet


The <xsl:stylesheet> element is the outermost element of a stylesheet. The synonym <xsl:transform> can be used as an alternative.

Changes in 2.0

A new attribute xpath-default-namespace has been added, to indicate how unprefixed element names in XPath expressions should be expanded.

A new attribute default-validation has been added, to indicate whether and how elements and attributes should be validated if they have no explicit [xsl:]validation or [xsl:]type attribute.

Format

 <xsl:stylesheet   id? = id   extension-element-prefixes? = tokens   exclude-result-prefixes? = tokens   version = number   xpath-default-namespace? = uri   default-validation? = "strict"  "lax"  "preserve" "strip">   use-when? = expression   <!-- Content: (xsl:import*, other-declarations) --> </xsl:stylesheet> 

Position

<xsl:stylesheet> (or its synonym, <xsl:transform> ) appears as the outermost element of every stylesheet module, except one that uses the simplified-stylesheet syntax described on page 119, in Chapter 3. It is used both on a principal stylesheet and on one that is imported or included into another stylesheet.

In addition to being the outermost element of the stylesheet module, the <xsl:stylesheet> element is usually the document element of an XML document-but not always; as described in Chapter 3, a stylesheet can also be embedded in another XML document.

Namespace Declarations

There will always be at least one namespace declaration on the <xsl:stylesheet> element, typically:

  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"  

This is necessary to identify the document as an XSLT stylesheet. The URI part must be written exactly as shown. The prefix «xsl » is conventional, and is used in all XSLT documentation including this book and the standard itself, but you could choose a different prefix if you wanted, for example «XSLT » . You would then have to name the element <XSLT:stylesheet> instead of <xsl:stylesheet> .

You can also make this the default namespace by using the following declaration:

  xmlns="http://www.w3.org/1999/XSL/Transform"  

In this case the element name will simply be <stylesheet> , and other XSLT elements will similarly be unprefixed, for example <template> rather than <xsl:template> . Although this works, it is not generally recommended, because the default namespace is then not available for literal result elements. The technique that works best is to reserve the default namespace for literal result elements that you want to go in the default namespace of the output document.

Important  

You may come across a stylesheet that uses the namespace declaration: xmlns:xsl=" http://www.w3.org/TR/WD-xsl "

This is not an XSLT stylesheet at all, but one written in WD-xsl, the working- draft dialect of XSL that Microsoft shipped in 1998 with Internet Explorer 5. This is a very different language, and is not described in this book.

Many stylesheets also need to declare the XML Schema namespace, typically as:

  xmlns:xs="http://www.w3.org/2001/XMLSchema"  

This is needed to declare the types of variables or parameters, or use conversions to types such as xs:integer and xs:date .

Attributes

Name

Value

Meaning

id

optional

XML Name

An identifier used to identify the <xsl:stylesheet> element when it is embedded in another XML document

version

mandatory

Number

Defines the version of XSLT required by this stylesheet. Use «2.0 » for a stylesheet that requires XSLT 2.0 features, or «1.0 » if you want the stylesheet to be portable between XSLT 1.0 and XSLT 2.0 processors

extension-element-prefixes

optional

Whitespace-separated list of NCNames

Defines any namespaces used in this stylesheet to identify extension elements

exclude-result-prefixes

optional

Whitespace-separated list of NCNames

Defines any namespaces used in this stylesheet that should not be copied to the output destination, unless they are actually used in the result document

xpath-default-namespace

optional

Namespace URI

Defines the namespace URI that is assumed for unprefixed element names and type names occurring in XPath expressions, patterns, and certain other constructs such as the SequenceType in an as attribute

default-validation

optional

«strict » , «lax » , «preserve » , or «strip »

Defines the validation applied to new element and attribute nodes when the instruction that creates them does not have an [xsl:] validation or [xsl:] type attribute

use-when

optional

XPath expression, restricted to use information available at compile time

Defines a condition that must be true if the contents of this stylesheet module are to be included in the stylesheet. It must be possible to evaluate the condition statically, which means it will often consist of a test on the value of the system-property () function

The attributes version , extension-element-prefixes , exclude-result-prefixes , and xpath-default-namespace can be specified on any element in the XSLT namespace. They can also be used on literal result elements, though in this case the attribute must be in the XSLT namespace, to distinguish it from user -defined attributes that are to be copied to the result tree. Collectively these attributes are referred to by names such as [xsl:] version , since they are sometimes namespace-prefixed.

These attributes are described here because they are usually used on the <xsl:stylesheet> element. They are not included in the proforma of other XSLT elements in order to save space.

The [xsl:] use-when attribute is more likely to appear on elements in a stylesheet other than the <xsl:stylesheet> or <xsl:transform> element. This attribute allows you to specify a compile-time conditional expression, and the element on which it appears will be included in the compiled stylesheet only if this condition is true. If the attribute is present on the <xsl:stylesheet> or <xsl:transform> element and takes the value false, the effect is as if the stylesheet module contained no top-level declarations. This attribute is described in Chapter 3 , on page 122.

In the case of version and xpath-default-namespace , the effective value of the attribute for a particular instruction in the stylesheet is the value on the nearest enclosing element, or the instruction itself, that has a value for this attribute. In the case of extension-element-prefixes and exclude-result-pref ixes , the values are cumulative-a namespace is an extension namespace or excluded namespace if it is listed as such on some enclosing instruction.

In practice the most useful place to specify these attributes is often on the <xsl:template> or <xsl:function> declarations, in which case they apply to the body of a template or function.

Content

The <xsl:stylesheet> element may contain XSLT elements referred to as top-level declarations. These elements are:

 <xsl:attribute-set> <xsl:character-map> <xsl:decimal-format> <xsl:function> <xsl:import> <xsl:import-schema> <xsl:include> <xsl:key> <xsl:namespace-alias> <xsl:output> <xsl:param> <xsl:preserve-space> <xsl:strip-space> <xsl:template> <xsl:variable> 

If there are any <xsl:import> elements, they must come before other top-level declarations.

The <xsl:stylesheet> element may also contain other elements provided they use a non-null namespace URI that is different from the XSLT namespace URI. If the namespace URI is recognized by the XSLT processor, it may interpret such elements in any way the vendor chooses, provided that the correct functioning of the stylesheet is not affected. If it does not recognize these elements, it should ignore them.

Effect

The rules are described below for each of the attributes.

The id Attribute

This attribute allows an <xsl:stylesheet> element to be referenced when it is contained within another XML document.

The precise usage is not defined in the standard, but the expectation is that this id attribute will allow an embedded stylesheet to be referenced in an <?xml-stylesheet?> processing instruction. An example is given in Chapter 3 on page 95. The specification points out that for this to work, it may be necessary for the id attribute to be declared in a DTD or schema as having the attribute type ID . However, not all XSLT processors impose this restriction.

The version Attribute

The version attribute defines the version of the XSLT specification that the stylesheet is relying on. At present there are two published versions of the XSLT standard, namely versions 1.0 and 2.0, so this attribute should take one of these two values.

Implementations of XSLT, even if they only implement version 1.0 of the standard, are required to behave in a particular way if the version specified is different from the version that they implement.

  • If the version attribute is «1.0 » , an XSLT 1.0 processor must report as errors any elements in the XSLT namespace that it doesn't recognize. For example, if it encounters the element <xsl:applyTemplate> it will flag this as an error (because the correct spelling is <xsl:apply-templates> ). Similarly, an XSLT 2.0 processor must reject unrecognized XSLT elements if the version attribute is set to «1.0 » or «2.0 » .

  • For an XSLT 1.0 processor, if the version attribute is any other value (including, oddly, a lower value than 1.0), the implementation must assume that the stylesheet is trying to use features defined in some version of XSLT that the software is unaware of. The same rule applies to an XSLT 2.0 processor if the version is greater than 2.0. So if the version attribute is «2.1 » , and the element <xsl:applyTemplate> appears, the software has to assume that this is a new element defined in version 2.1 of the standard, rather than a misspelling of <xsl:apply-templates> . The XSLT specification calls this forwards-compatible processing mode. In this mode, the <xsl:applyTemplate> element will be rejected only if (a) an attempt is made to evaluate it, and (b) it has no <xsl:fallback> child element. If it does have an <xsl:fallback> child element, this will be evaluated in place of the unrecognized parent element. This is described in greater detail under <xsl:fallback> on page 271.

  • This means that an XSLT 1.0 processor that encounters a stylesheet specifying «version="2.0" » , and containing say an <xsl:analyze-string> instruction (which is perfectly legal in XSLT 2.0), will not reject the stylesheet at compile time. Moreover, if the <xsl:analyze-string> instruction has an <xsl:fallback> child element, there will be no runtime error either: The <xsl:fallback> element will be evaluated, and the rest of the <xsl:analyze-string> instruction ignored. This is all a consequence of the way XSLT 1.0 was defined, with forwards compatibility in mind; XSLT 1.0 processors should work this way even if they were written years before the XSLT 2.0 specification was published.

Forwards-compatible mode also affects the handling of other apparent errors. For example if the version attribute is «2.0 » (or in the case of an XSLT 1.0 processor, «1.0 » ), any unrecognized attributes or values of attributes on an XSLT element are reported as errors, but in forwards-compatible mode, such attributes are ignored. Similarly, in forwards-compatible mode a misplaced XSLT element such as <xsl: sort > , if found within a sequence constructor, will not be reported as an error until you try to evaluate it.

The version attribute applies to the entire stylesheet, except any parts contained within an XSLT element that has a version attribute, or a literal result element that has an xsl:version attribute. Its scope is the stylesheet module, not the full stylesheet tree constructed by applying <xsl:include> and <xsl:import> elements.

Note that in XSLT 1.0, the version attribute was allowed only on the <xsl:stylesheet> element, and xsl:version was allowed on literal result elements. In XSLT 2.0 this has been relaxed so version can be specified on any element in the XSLT namespace. If your stylesheet is likely to be executed by an XSLT 1.0 processor, it is best to use it only in the places where it was allowed in XSLT 1.0.

The extension-element-prefixes Attribute

This attribute identifies a set of namespaces used for extension instructions. Extension instructions may be defined by an implementor, a user, or a third party. They can be used anywhere an instruction can be used, that is, within a sequence constructor. If an element is found in a sequence constructor that is not in the XSLT namespace, then it must either be an extension instruction or a literal result element. If its namespace is the same as a namespace identified in the [xsl:] extension-element-prefixes attribute of the containing <xsl:stylesheet> element, of some other containing element, or of the element itself, then it will be treated as an extension instruction, otherwise it will be treated as a literal result element.

The value of the attribute is a whitespace-separated list of prefixes; each of these prefixes must identify a namespace declaration present on the <xsl:stylesheet> element. The default namespace (the namespace declared using the xmlns attribute) may be designated as an extension element namespace by including the pseudoprefix «#default » .

The scope of the extension-element-prefixes attribute is the stylesheet module, not the full stylesheet tree constructed by applying <xsl:include> and <xsl:import> elements.

If a namespace is designated as an extension element namespace, then every XSLT processor will recognize that these elements are extension instructions. However, some XSLT processors may be unable to evaluate them. For example, if the namespace http://www.jclark.com/xt/extensions is designated as an extension namespace, then both xt and Xalan will recognize that these elements are extensions, but the likelihood is that xt will know how to handle them and Xalan won't. If the processor knows how to evaluate the instruction, it does so; otherwise, it looks to see if the element contains an <xsl:fallback> instruction. If it does, the <xsl:fallback> instruction is evaluated; otherwise, an error is reported.

It is necessary to designate a namespace as an extension element namespace only to distinguish extension instructions from literal result elements. At the top level of the stylesheet, there is no risk of confusion. Any implementation can define its own top-level elements, using its own namespace, and other implementations will simply ignore these elements, treating them as data. So the extension-element-prefixes attribute is not needed to identify top-level elements used as vendor or user extensions. For example, you can use <msxml:script> as a top-level declaration, and processors other than Microsoft MSXML3 will probably ignore it (though there is nothing that says they have to).

The exclude-result-prefixes Attribute

This attribute defines a set of namespaces that are not to be copied into the result tree.

The XSLT processor is required to produce a correct tree that conforms with the data model (as described on page 48, in Chapter 2) and with the XML Namespaces rules, so you will never find yourself with an output file using namespace prefixes that have not been declared. However, you can easily find yourself with a file containing unnecessary and unwanted namespace declarations, for example, declarations of namespaces that occur on nodes in your source document but are not used in the output document, or namespaces for extension functions that are used only in the stylesheet. These extra namespace declarations usually don't matter, because they don't affect the meaning of the output file, but they can clutter it up. They can also affect validation if you are trying to create a result document that conforms to a particular DTD. So this attribute is provided to help you get rid of them.

More specifically , the XSLT specification requires that when a literal result element in the stylesheet is evaluated, the element is copied into the result tree along with all its namespace nodes, except for the XSLT namespace and any namespace that defines extension instructions. An element has a namespace node for every namespace that is in scope, including namespaces defined on ancestor elements as well as on the element itself, so the namespaces copied over include not only the namespaces defined on the literal result element, and those that are actually used on the literal result element, but even those that are merely available for use.

Very often, of course, one literal result element will be a child or descendant of another, and the namespace nodes on the child element will include copies of all the namespace nodes on the parent element. For example, consider the stylesheet below:

  <xsl:stylesheet version="1.0"   xmlns:xsl="http://www.w3.org/1999/XSL/Transform"/>   <xsl:template match="/">   <acme:document xmlns:acme="http://acme.com/xslt">   <acme:chapter>   Once upon a time ...   </acme:chapter>   </acme:document>   </xsl:template>   </xsl:stylesheet>  

This is represented by the tree shown in Figure 5-12, using the same notation as previously seen in Chapters 2 and 3. Although there are only two namespace declarations, these are propagated to all the descendant elements, so for example the <acme:chapter> element has two namespace nodes even though there are no namespace declarations on the element. (It also has a namespace node for the «xml » namespace, which is not shown in Figure 5-12.)

click to expand
Figure 5-12

The specification says that each literal result element is copied with all its namespace nodes (but excluding the XSLT namespace), so the result tree will resemble Figure 5-13 (again, the «xml » namespace nodes are omitted).

click to expand
Figure 5-13

Both elements, <acme:document> and <acme:chapter> , have a namespace node for the «acme » namespace. However, this doesn't mean that the namespace declaration will be repeated unnecessarily in the output file: We're talking here about the abstract tree that is created, not the final serialized XML file. Avoiding duplicate namespace declarations is entirely the job of the XSLT serializer, and most serializers will produce the following output, shown indented for clarity:

  <acme:document xmlns:acme="http://acme.com/xslt">   <acme:chapter>   Once upon a time ...   </acme:chapter>   </acme:document>  

The exclude-result-prefixes attribute isn't present to get rid of duplicate declarations, it's present to get rid of declarations that aren't wanted at all, which is a different matter entirely. For example suppose the stylesheet was like this:

 <xsl:stylesheet version="1.0"    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"    xmlns:var="http://another.org/xslt" /> <xsl:variable name="var:x" select="17"/> <xsl:template match="/">    <acme:document xmlns:acme="http://acme.com/xslt">       <acme:chapter>          Once upon a time ...       </acme:chapter>    </acme:document> </xsl:template> </xsl:stylesheet> 

Then although the sequence constructor has not changed, the <acme:document> and <acme:chapter> elements each now have an extra namespace node, and this will be copied to the output file even though it is unused, resulting in the output:

  <acme:document xmlns:acme="http://acme.com/xslt"   xmlns:var="http://another.org/xslt">   <acme:chapter>   Once upon a time ...   </acme:chapter>   </acme:document>  

Why can't the XSLT processor simply include all the namespaces that are actually used in element and attribute names, and omit the rest? The line of thinking is that many XML applications, like XSLT itself, will use the namespace mechanism to create unique values within their own data. For example, namespace prefixes might be used in attribute values as well as attribute names. The XSLT processor can't distinguish these from ordinary values, so it has to play safe.

So if there are namespaces you don't want in the output tree, you can specify them in the exclude-result-prefixes attribute of the <xsl:stylesheet> element. The attribute is a list of namespace prefixes, separated by whitespace, and with the option to include the default namespace under the pseudoprefix «#default » . If you want more precise control (though it is rarely needed) you can also specify [xsl:] exclude-result-prefixes on any element in the stylesheet, remembering that the attribute must be prefixed when it appears on a literal result element, and unprefixed when it appears on an XSLT element. It affects all literal result elements that are textually within its scope.

The prefix, as always, is simply a way of referring to the associated namespace URI: It is the namespace URI that is really being excluded, not the prefix itself. So if the same namespace URI is declared again with a different prefix, it is still an excluded namespace.

The [xsl:] exclude-result-prefixes attribute applies only to namespace nodes copied from the stylesheet using literal result elements. It does not affect namespace nodes copied from the source document using <xsl:copy> or <xsl:copy-of> ; these can be suppressed by using the copy-namespaces attribute on the instruction itself.

Like the other attributes on the <xsl:stylesheet> element, the exclude-result-prefixes attribute applies only to elements actually within the stylesheet module, not to those brought in using <xsl:include> or <xsl:import> .

What happens if you try to exclude a namespace that is actually needed because it is used in the result tree? The XSLT processor is obliged to generate output that conforms to the Namespaces Recommendation, so it will ignore the request to exclude this namespace. Or more accurately, the evaluation of the literal result element will not cause the namespace node to be copied, but the namespace fixup process that comes into play when the element has been constructed will then generate namespace nodes for any namespaces that were missing. Namespace fixup is described under <xsl:element> on page 265.

The xpath-default-namespace Attribute

A common source of bewilderment for XSLT 1.0 users is when they see a source document that looks like this:

  <para>Some text here</para>  

and they try to match this with a template rule like this

  <xsl:template match="para">  

or perhaps to output the value with an expression like this

  <xsl:value-of select="para"/>  

and nothing happens. Only with experience do you learn to look near the top of the document for a tell-tale default namespace declaration:

  <document xmlns="http://www.megacorp.com/ns">  

Sometimes the default namespace declaration is even more carefully hidden, being placed as a default attribute value in the DTD. The XHTML specification is an example that uses this infuriating technique: hiding in its DTD is the snippet:

  <!ELEMENT html (head, body)>   <!ATTLIST html   %il8n;   id          ID             #IMPLIED   xmlns       %URI;          #FIXED 'http://www.w3.org/1999/xhtml'   >  

which has the effect that every element you use in a document that invokes this DTD, an element written as <br/> perhaps, is actually in the namespace « http://www.w3.org/1999/xhtml » although you probably didn't know it.

When you write «match="br" » or «select="br" » in your stylesheet, you are asking for <br> elements in the null namespace, and you will not match <br> elements in any non-null namespace. To match elements in the namespace « http://www.w3.org/1999/xhtml » , you first have to declare this namespace in your stylesheet (with a specific prefix):

  <xsl:stylesheet . . .   xmlns:xhtml="http://www.w3.org/1999/xhtml">  

and then use this prefix whenever you refer to elements in this namespace: «match="xhtml:br" » and «select="xhtml:br" ».

XSLT 2.0 hasn't found any way of eliminating the frustration of not realizing that the source elements were actually in a namespace, but it has eliminated the tedium of adding all the prefixes to your patterns and XPath expressions once you've realized what the problem is. You can now declare the namespace as being the default namespace for elements in XPath expressions by writing:

  <xsl:stylesheet . . .   xpath-default-namespace="http://www.w3.org/1999/xhtml">  

and the names used in expressions and patterns can then remain unprefixed.

As with other attributes on the <xsl:stylesheet> element, this attribute can also be specified on other elements in the stylesheet, including literal result elements if the attribute is prefixed with the XSLT namespace prefix. This allows you to define a different default XPath namespace in different regions of the stylesheet, which is useful if the stylesheet is processing different source documents. (But it might be simpler in this case to split the stylesheet into different modules.) The attribute affects everything that is textually within its scope, and doesn't extend to included or imported modules.

The value is a namespace URI rather than a prefix, which means that the stylesheet doesn't actually need to declare this namespace. This is convenient because it means the namespace won't be automatically copied into the result document. You can also set it to a zero-length string to restore the default setting, which is that unprefixed names are assumed to refer to elements that are in no namespace.

The XPath default namespace affects unprefixed names appearing in the following contexts:

  • Element names (but not attribute names) appearing in path expressions: That is, an NCName used as a NameTest in an AxisStep , when the axis is one that selects elements.

  • Element names used similarly in patterns.

  • Element names and type names (but not attribute names) used in the SequenceType syntax for defining types, whether the SequenceType syntax is used within an XPath expression, or on its own within an as attribute in the stylesheet

  • Type names used in an XPath cast expression, for example «cast as part-number ("MF00325Z") » .

  • Type names used in a type attribute in the stylesheet.

  • Element names used in <xsl:strip-space> and <xsl:preserve-space> .

Note that although the namespace applies to unprefixed names appearing in a cast expression, it does not apply to the names of functions, including constructor functions such as «part-number ("MF00325Z") » where the function name is based on the name of a user-defined type in a schema. With constructor functions the namespace must always be given explicitly; an unprefixed function name can only be used for functions in the core library (that is, standard XSLT and XPath functions).

Another consequence of this rule is that if you import a schema that has no target namespace, you cannot use constructor functions to create instances of the atomic types defined in this schema. Instead, you must use the more long-winded cast syntax. (In fact, this is the main reason that the cast syntax has been retained in the XPath language.)

The XPath 2.0 specification refers to a concept called the default function namespace, which is the namespace in which unprefixed function names are located. Although XPath allows this to be defined as part of the evaluation context, XSLT does not pass this capability on to the user. When XPath expressions are used in XSLT stylesheets, the default function namespace is always the standard namespace http://www.w3.org/2003/11/xpath-functions . This means that calls on standard functions such as position() and last() never need to be prefixed in XSLT, though you can use a prefix that is bound to the standard namespace if you really want to.

The default-validation Attribute

Like the other attributes we've been discussing, the default-validation attribute applies to everything that is textually within the stylesheet module. Unlike the other attributes, it can't be overridden with a different declaration on an inner element in the stylesheet. (I don't think there's any good reason for this restriction; it was put there simply to avoid adding unnecessary complexity).

This attribute applies to every instruction in the stylesheet that is allowed to take a validation or type attribute, but where neither of these attributes is actually present. It also affects literal result elements, which are allowed to take an xsl:type or xsl:validation attribute, in the same way. The effect is to supply a default value for the [xsl:]validation attribute on these instructions or literal result elements.

The possible values of the attribute are «strict » , «lax » , «preserve » , or «strip » . The meanings of these values are explained under each instruction that takes a validation attribute, and vary slightly from one instruction to another, depending on whether it is dealing with single nodes or multiple nodes, elements or attributes.

The use-when Attribute

This attribute is a late addition to the language. The attribute may be specified on any element in the stylesheet (if specified on a literal result element, it is named «xsl:use-when » ) and its value is an XPath expression. Although the full XPath syntax is allowed, the context for evaluation of the expression is severely restricted, which means that the expression cannot refer to anything in the source document or the stylesheet. In practice this means it is restricted to testing the results of functions such as system-property() , function-available() , and element-available() .

The expression is evaluated at compile time, and if its effective boolean value is false, the element on which it appears is effectively excluded from the stylesheet module at compile time. If the attribute is used on the <xsl:stylesheet> or <xsl:transform> element the effect is slightly different: The element itself is not excluded (because this would make the stylesheet invalid); instead, all the top-level declarations are excluded, so the stylesheet module becomes empty. This is only useful, of course, for an included or imported module.

Usage and Examples

The <xsl:stylesheet> element is always the outermost element of the stylesheet (though the stylesheet may be embedded in another document). It will always include:

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

The various possible attributes are considered in the sections that follow.

The id Attribute

If the XSLT processor you are using supports embedding of stylesheets within the source document that they are to transform, then the typical layout will be like this:

  <?xml version="1.0"?>   <?xml-stylesheet href="#style" type="text/xsl"?>   <!DOCTYPE data [   <!ATTLIST xsl:stylesheet id ID #REQUIRED >   ]>   <data>   ...   ...   <xsl:stylesheet id="style" version="2.0"   xmlns:xsl="http://www.w3.org/1999/XSL/Transform"   >   <xsl:include href="module1.xsl"/>   <xsl:include href="module2.xsl"/>   <xsl:template match="xsl:*"/>   </xsl:stylesheet>   </data>  

Note that when this structure is used, the stylesheet will be presented with the entire source document, including a copy of itself. The stylesheet therefore needs to be written to handle its own elements in an appropriate way, hence the empty template rule that matches all elements in the XSLT namespace.

XSLT 2.0 defines the media type (MIME type) «application/xslt+xml » for XSLT stylesheet modules, but the unofficial usage «text/xsl » is much more widely supported in today's products.

The version Attribute

If your stylesheet only uses features from XSLT 1.0, it is best to specify «version="1.0" » on the <xsl:stylesheet> element. Then it will work with any XSLT processor that conforms to XSLT 1.0 or a later version of the standard.

If the stylesheet uses 2.0 features, you should specify «version="2.0" » on the <xsl:stylesheet> element. An XSLT 2.0 that encounters a stylesheet that specifies «version="1.0" » at the start of the principal stylesheet module is supposed to give you a warning about possible incompatibilities, and then process the stylesheet as if it were a 2.0 stylesheet, but with backwards compatiblity mode switched on. (This doesn't guarantee 100% compatibility, but it's pretty close.)

If your stylesheet says «version="1.0" » this won't stop you using XSLT 2.0 features; an XSLT 2.0 processor isn't expected to look at every construct you use and decide whether it would have been allowed in XSLT 1.0. But for certain specific features, it causes XSLT 2.0 and XPath 2.0 to behave differently. The main examples of this are:

  • In function calls expecting a string or a number as an argument, a processor running in 1.0 mode will cast the supplied value to a string or number as appropriate. In 2.0 mode, stricter type checking prevails, and you have to do such casts yourself. However, if the argument you supply is a node in a schema-less document (type annotation xs:untyped or xs:untypedAtomic ) then a cast will still be performed.

  • In function calls, if you supply a sequence containing more than one value where a single value is expected, then in 1.0 mode all but the first value will be ignored. In 2.0 mode this is a type error: If you only want to process the first item in the sequence, you must select it explicitly using the predicate «[1] » .

  • Similarly, in certain XSLT contexts, a processor running in 1.0 mode applies the "first item" rule when you supply a sequence of values, but either reports an error, or processes the whole sequence, when in 2.0 mode. The most common example of this is in <xsl:value-of> : If you write <xsl:value-of select="book/author"/> in 1.0 mode then only the first author of the first book will be displayed, while in 2.0 mode this will produce a list of all the authors of all the selected books, space-separated. For more details, see <xsl:value-of> on page 465.

XSLT 2.0 allows you to put the version attribute on any element in the stylesheet, and at first sight a nice idea would be to flag any template rule that uses XSLT 2.0 features by labeling it with the attribute «version="2.0" » . Unfortunately , however, XSLT 1.0 doesn't allow the version attribute to appear on the <xsl:template> element, so if you want your stylesheet to still work with 1.0, this won't work. A better idea is probably to put all the template rules that depend on XSLT 2.0 in a separate module, and label this module with «version="2.0" » at the <xsl:stylesheet> level. Of course, you will still need to provide 1.0 fallback behavior whenever you use a 2.0 construct.

The extension-element-prefixes Attribute

This attribute should be set to a list of all the prefixes you are using for extension instructions in your stylesheet. The most common cases are either to omit it entirely, or to include a single prefix for the namespace used by the vendor of your chosen XSLT processor for their own proprietary extensions. There will always be a namespace declaration for this namespace on the <xsl:stylesheet> element as well.

For example, if you are using Saxon:

  <xsl:stylesheet   version="2.0"   xmlns:xsl="http://www.w3.org/1999/XSL/Transform"   xmlns:saxon="http://saxon.sf.net/"   extension-element-prefixes="saxon"   >  

Don't include the vendor's prefix unless you are actually using their proprietary extensions in the stylesheet. You don't need to include this attribute to use proprietary top-level elements such as <msxml:script> , or to use extension functions: You need it only if you want to use vendor-defined instructions within a sequence constructor, where they would otherwise be assumed to be literal result elements.

If your usage of vendor extensions is highly localized within the stylesheet, it is better to identify them using the xsl:extension-element-prefixes attribute of the extension element itself, or of a literal result element that surrounds the sequence constructor where the extensions are actually used. This aids portability and makes it easier to see which parts of the stylesheet are standard and which parts use proprietary extensions.

If you want to use extensions supplied by several different vendors , you can list them all in this attribute. An XSLT processor from one vendor won't object to finding another vendor's namespace in the list; it will only object if it is actually asked to evaluate a proprietary instruction that it doesn't understand, and even then if there is an <xsl:fallback> child element that defines the fallback behavior it will carry on calmly executing that in place of the unrecognized instruction.

Although extension elements supplied by XSLT product vendors are likely to be the most common case, it's also possible in principle to install third-party extensions or to write your own (however, the APIs for doing so will be different for each vendor). So everything we've said about the vendor's extensions applies equally to your own extensions or those acquired from a third party.

For more information about the extensions provided by various vendors in their products, see the documentation for the relevant product.

An inventive way of using the extension-element-prefixes attribute is to flag elements that you want to reserve for debugging or annotation. For example, if you include the following element within a sequence constructor anywhere in the stylesheet, then the normal action will be to output an element to the result tree, showing the current values of the variables $var1 and $var2 .

  <debug:write var1="{$var1}" var2="{$var2}"><xsl:fallback/></debug:write>  

When you no longer need to use this debugging instruction, you can disable it simply by declaring «debug » as an extension element prefix. This time the <xsl:fallback/> action will be taken, because the processor doesn't recognize the extension instruction.

The exclude-result-prefixes Attribute

The simplest way to decide which namespace prefixes to list here is by trial and error. Run the stylesheet, and if the output document contains namespace declarations that clearly serve no useful purpose, add them to the exclude-result-prefixes attribute and run the stylesheet again.

The XSLT namespace itself and namespaces used for extension elements will be excluded automatically. However, the stylesheet is also likely to contain references to the schema namespace and perhaps the «xdt » namespaces, which you may not want in your result document. It will also contain any namespace you have used for defining your local stylesheet functions, which you almost certainly don't want in the result document.

A common cause of unwanted namespace declarations finding their way into the result document is where your stylesheet needs to refer to namespaces used in the source document, for example in a template match pattern, but where none of these elements is copied into the destination document.

For example:

  <xsl:stylesheet   version="2.0"   xmlns:xsl="http://www.w3.org/1999/XSL/Transform"   xmlns:po="http://accounting..org/xslt"   exclude-result--prefixes="po"   >   <xsl:template match="po:purchase-order">   <order-details>   ...   </order-details>   </xsl:template>   </xsl:stylesheet>  

Here the «po » namespace would be copied into the result document if it weren't for the exclude-result-prefixes attribute, because it is in scope when the literal result element <order-details> is evaluated.

As with the other <xsl:stylesheet> attributes, you don't have to apply the exclusion to the whole stylesheet if you don't want to, you can also apply it to any part of the stylesheet by using the xsl:exclude-result-prefixes attribute on any literal result element. It's probably a good idea in practice to keep the declaration of a namespace and the directive that excludes it from the result document together in one place.

The xpath-default-namespace Attribute

I would recommend always using this attribute if your source documents generally use a default namespace declaration; the value should be the namespace URI of this default namespace declaration. Specifying an xpath-default-namespace will not stop existing code working that uses explicit prefixes to refer to names in this namespace.

One thing to watch out for is that if your stylesheet creates and uses temporary trees, the chances are that these don't use namespaces. Specifying an xpath-default-namespace makes it impossible to refer to names that are in the null namespace, for example elements on such a temporary tree (you can't bind a namespace prefix to the null namespace, unfortunately). In this situation you can override the xpath-default-namespace in the relevant region of your stylesheet by writing «xpath-default-namespace="" ».

If your stylesheet processes multiple source documents of different types, similar considerations apply. In this case it might be clearer to use explicit namespace prefixes for everything.

The default-validation Attribute

This attribute can take the value «strict », «lax », «preserve », or «strip ». It affects every literal result element, and every <xsl:element>, <xsl:copy>, <xsl:copy-of> and <xsl:result-document> instruction within the stylesheet module, unless it has its own validation attribute. Unlike the other attributes on <xsl:stylesheet>, this attribute cannot be overridden on an inner element for a region of the stylesheet; it can only be overridden on the actual instruction that uses it.

Specifying «default-validation="strict" » is probably not usually a good idea, because it means that any attempt to create an element or attribute that does not have a global declaration in the schema will cause a failure. All the other three values might be sensible under different circumstances. «lax » means that schema validation will be carried out whenever possible, which is useful if you want to detect the maximum number of errors. «preserve » is useful if source documents carry type annotations and you do not want these to be lost. «strip » is the default value, so specifying it here actually has no effect, but this option is useful if you want the stylesheet to behave as much as possible as a non-schema-aware stylesheet in which source documents are regarded as untyped.

In practice I think that «validation="preserve" » is likely to be the only option that's really useful. Given a schema-aware processor, and a stylesheet whose main job is to copy a selection of the nodes from the source document across to the result document with as few changes as possible, for further transformation by another stylesheet later on in the pipeline, it makes sense to preserve all the existing type annotations. However, check the specification of the individual instructions. <xsl:copy validate="preserve"> probably doesn't do what you imagine. Since <xsl:copy> can completely change the content of an element, the type annotation on the element being copied is no longer reliable, so it isn't retained, even with this option. When a subtree is copied in its entirety, with no changes (typically using <xsl:copy-of> ), it makes sense to retain type annotations. As soon as any changes are made, the result can only contain type annotations if you put it through schema validation.

You need to think about whether you actually want the result tree to be validated at all. Validation of the result against a schema can, of course, be very useful, both to detect errors in your stylesheet, and to ensure that the tree is annotated with type information for use by the next process in the pipeline. But there are two reasons you might not want this done:

  • You might actually want to produce a document that's invalid according to the schema. For example, you might have a schema for a university application form that includes required entries for the student's personal details such as name and address. But the purpose of your transformation might be to extract data for statistical purposes in which this personal information is omitted. You can't specify two different schemas for the source document and the result document if they use the same namespace, so you might just have to accept that in this situation, the result document will not validate.

  • There are probably many transformations where validation of the result adds little value, or where it is simpler to do it as a completely separate process, once the transformation is complete. Just because the facility is available doesn't mean you have to use it.

One thing you might want to try is to have validation switched on while you are doing system testing of your stylesheet, or after you introduce changes, and to have it switched off once everything starts running smoothly. This isn't particularly easy to achieve, but controlling validation from the <xsl:stylesheet> level should make it easier than it would be otherwise. But I would be inclined, in this situation, to switch validation on or off at the level of the <xsl:result-document> instruction, which is described on page 414.

The use-when Attribute

This attribute is provided to allow you to write stylesheets that are portable across different XSLT processors. For example, you can specify «use-when="system-property ('xsl:is-schema-aware')='yes'" » to mark a section of stylesheet code that should be ignored by a processor that is not schema-aware, or you can test the «xsl:vendor » system property to include sections of code that are specific to particular XSLT implementations. You can also use the function-available() function to conditionally include or exclude sections of code based on whether a particular extension function is available in the implementation you are running on.

There are more examples of the use of this attribute in Chapter 3 (see page 122). It can be used on any XSLT element, both declarations (notably <xsl:include> , <xsl:import> , and <xsl:import-schema> ), and instructions. Just remember that the expression cannot access the source document, and it cannot access any variables: It is designed only to test properties of the environment in which the stylesheet is compiled.

See Also

<xsl:transform> on page 465




XSLT 2.0 Programmer's Reference
NetBeansв„ў IDE Field Guide: Developing Desktop, Web, Enterprise, and Mobile Applications (2nd Edition)
ISBN: 764569090
EAN: 2147483647
Year: 2003
Pages: 324

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net