This section describes the overall structure of a stylesheet as a collection of XML documents.
[Definition: The XSLT namespace
has the URI http://www.w3.org/1999/XSL/Transform
. It is used to
identify elements, attributes, and other names that have a special meaning defined
in this specification.]
Note:
The 1999
in the URI indicates the year in which the URI was allocated
by the W3C. It does not indicate the version of XSLT being used, which is
specified by attributes (see 3.7 Stylesheet Element and 3.8 Simplified Stylesheet Modules).
XSLT processors must use the XML namespaces mechanism [Namespaces in XML] to recognize elements and attributes from this namespace. Elements from the XSLT namespace are recognized only in the stylesheet and not in the source document. The complete list of XSLT-defined elements is specified in D Element Syntax Summary. Implementations must not extend the XSLT namespace with additional elements or attributes. Instead, any extension must be in a separate namespace. Any namespace that is used for additional instruction elements must be identified by means of the extension instruction mechanism specified in 24.2 Extension Instructions.
This specification uses a prefix of xsl:
for referring to elements in
the XSLT namespace. However, XSLT stylesheets are free to use any prefix, provided
that there is a namespace declaration that binds the prefix to the URI of the XSLT
namespace.
Note:
Throughout this specification, an element or attribute that is in no namespace, or an expanded QName whose namespace part is an empty sequence, is referred to as having a null namespace URI.
Note:
By convention, the names of XSLT
elements, attributes and functions are all lower-case;
they use hyphens to separate words, and they use abbreviations only if these already
appear
in the syntax of a related language such as XML or HTML. Names of types defined in
XML Schema are regarded as single words and are capitalized exactly as in XML
Schema. This sometimes leads to composite function names such as
current-dateTime
FO30.
[Definition: An element from the XSLT namespace may have any attribute not from the XSLT namespace, provided that the expanded QName (see [XPath 3.0]) of the attribute has a non-null namespace URI. These attributes are referred to as extension attributes.] The presence of an extension attribute must not cause the principal result or any secondary result of the transformation to be different from the results that a conformant XSLT 3.0 processor might produce. They must not cause the processor to fail to signal an error that a conformant processor is required to signal. This means that an extension attribute must not change the effect of any instruction except to the extent that the effect is implementation-defined or implementation-dependent.
Furthermore, if serialization is performed using one of the serialization methods described in [XSLT and XQuery Serialization], the presence of an extension attribute must not cause the serializer to behave in a way that is inconsistent with the mandatory provisions of that specification.
Note:
Extension attributes may be used to modify the behavior of extension functions and extension instructions. They may be used to select processing options in cases where the specification leaves the behavior implementation-defined or implementation-dependent. They may also be used for optimization hints, for diagnostics, or for documentation.
Extension attributes may also be
used to influence the behavior of the serialization methods xml
,
xhtml
, html
, or text
, to the extent that
the behavior of the serialization method is implementation-defined or implementation-dependent. For example, an extension attribute might
be used to define the amount of indentation to be used when
indent="yes"
is specified. If a serialization method other than
one of these four is requested (using a prefixed QName in the method parameter)
then extension attributes may influence its behavior in arbitrary ways. Extension
attributes must not be used to cause the standard serialization methods to
behave in a non-conformant way, for example by failing to report serialization
errors that a serializer is required to report. An implementation that wishes to
provide such options must create a new serialization method for the purpose.
An implementation that does not recognize the name of an extension attribute, or that does not recognize its value, must perform the transformation as if the extension attribute were not present. As always, it is permissible to produce warning messages.
The namespace used for an extension attribute will be copied to the result tree in the normal way if it is in scope
for a literal result element.
This can be prevented using the [xsl:]exclude-result-prefixes
attribute.
The following code might be used to indicate to a particular implementation that
the xsl:message
instruction is to ask the user for confirmation
before continuing with the transformation:
<xsl:message abc:pause="yes" xmlns:abc="http://vendor.example.com/xslt/extensions"> Phase 1 complete </xsl:message>
Implementations that do not recognize the namespace
http://vendor.example.com/xslt/extensions
will simply ignore the
extra attribute, and evaluate the xsl:message
instruction in the
normal way.
[ERR XTSE0090] It is a static error for an element from the XSLT namespace to have an attribute whose namespace is either null (that is, an attribute with an unprefixed name) or the XSLT namespace, other than attributes defined for the element in this document.
The media type application/xslt+xml
has been registered for XSLT stylesheet
modules.
The definition of the media type is at [XSLT Media Type].
This media type should be used for an XML document containing a standard stylesheet module at its top level, and it may also be used for a simplified stylesheet module. It should not be used for an XML document containing an embedded stylesheet module.
[Definition: There are a number of
standard attributes that may appear on any XSLT element: specifically
default-collation
, default-mode
,
default-validation
,
exclude-result-prefixes
, expand-text
, extension-element-prefixes
,
use-when
, version
, and
xpath-default-namespace
.]
These attributes may also appear on a literal result element, but in this case, to distinguish them from
user-defined attributes, the names of the attributes are in the XSLT namespace. They are thus typically written
as xsl:default-collation
, xsl:default-mode
, xsl:default-validation
,
xsl:exclude-result-prefixes
, xsl:expand-text
,
xsl:extension-element-prefixes
, xsl:use-when
,
xsl:version
, or xsl:xpath-default-namespace
.
It is recommended that all these attributes should also be permitted on extension instructions, but this is at the discretion of the implementer of each extension instruction. They may also be permitted on user-defined data elements, though they will only have any useful effect in the case of data elements that are designed to behave like XSLT declarations or instructions.
In the following descriptions, these attributes are referred to generically as
[xsl:]version
, and so on.
These attributes all affect the element they appear on, together with any elements and attributes that have that element as an ancestor. The two forms with and without the XSLT namespace have the same effect; the XSLT namespace is used for the attribute if and only if its parent element is not in the XSLT namespace.
In the case of [xsl:]default-collation
, [xsl:]expand-text
,
[xsl:]version
, and [xsl:]xpath-default-namespace
, the value
can be overridden by a different value for the same attribute appearing on a
descendant element. The effective value of the attribute for a particular stylesheet
element is determined by the innermost ancestor-or-self element on which the
attribute appears.
In an embedded stylesheet module, standard attributes appearing on ancestors of the outermost element of the stylesheet module have no effect.
In the case of [xsl:]exclude-result-prefixes
and
[xsl:]extension-element-prefixes
the values are cumulative. For these
attributes, the value is given as a whitespace-separated list of namespace prefixes,
and the effective value for an element is the combined set of namespace URIs
designated by the prefixes that appear in this attribute for that element and any
of
its ancestor elements. Again, the two forms with and without the XSLT namespace are
equivalent.
The effect of the [xsl:]use-when
attribute is described in 3.13.1 Conditional Element Inclusion.
Because these attributes may appear on any XSLT
element, they are not listed in the syntax summary of each individual
element. Instead they are listed and described in the entry for the
xsl:stylesheet
, xsl:transform
, and xsl:package
elements only. This
reflects the fact that these attributes are often used on the outermost element of the stylesheet, in which case they apply to
the entire stylesheet module
or package manifest.
Note that the effect of these attributes does not extend to stylesheet modules referenced by
xsl:include
or xsl:import
declarations, nor to packages referenced using
xsl:use-package
.
For the detailed effect of each attribute, see the following sections:
[xsl:]default-collation
[xsl:]default-mode
[xsl:]default-validation
see 25.4 Validation
[xsl:]exclude-result-prefixes
[xsl:]expand-text
[xsl:]extension-element-prefixes
[xsl:]use-when
[xsl:]version
see 3.9 Backwards Compatible Processing and 3.10 Forwards Compatible Processing
[xsl:]xpath-default-namespace
see 5.1.2 Unprefixed Lexical QNames in Expressions and Patterns
[Definition: An explicit package is
represented by an xsl:package
element, which will generally be
the outermost element of an XML document. When the
xsl:package
element is not used explicitly, the entire
stylesheet comprises a single implicit package.] (This
specification does not preclude the xsl:package
being embedded in
another XML document, but it will never have any other XSLT element as an
ancestor).
<xsl:package
id? = id
name? = uri
package-version? = string
version = decimal
input-type-annotations? = "preserve" | "strip" | "unspecified"
declared-modes? = boolean
default-mode? = eqname | "#unnamed"
default-validation? = "preserve" | "strip"
default-collation? = uris
extension-element-prefixes? = prefixes
exclude-result-prefixes? = prefixes
expand-text? = boolean
use-when? = expression
xpath-default-namespace? = uri >
<!-- Content: ((xsl:expose | declarations)*) -->
</xsl:package>
[Definition: The content of the
xsl:package
element is referred to as the package
manifest].
The version
attribute indicates the
version of the XSLT language specification to which the package manifest conforms.
The value should normally be
3.0
. If the value is numerically less than 3.0
, the
content of the xsl:package
element is processed using the rules
for backwards compatible
behavior (see 3.9 Backwards Compatible Processing). If the value is
numerically greater than 3.0
, it is processed using the rules for
forwards compatible behavior (see 3.10 Forwards Compatible Processing).
A package typically has a name, given in its name
attribute, which must be an absolute URI. Unnamed packages are
allowed, but they can only be used as the “top level” of an application; they cannot
be the target of an xsl:use-package
declaration in another
package.
A package may have a version identifier, given in
its package-version
attribute. This is used to distinguish different
versions of a package. The value of the version
attribute, after trimming leading and trailing whitespace, must
conform to the syntax given in 3.5.1 Versions of a Package. If no version
number is specified for a package, version 1
is assumed.
The attributes default-collation
, default-mode
, default-validation
,
exclude-result-prefixes
, expand-text
,
extension-element-prefixes
, use-when
,
version
, and xpath-default-namespace
are standard
attributes that can appear on any XSLT element, and potentially affect all descendant
elements. Their meaning is described in 3.4 Standard Attributes.
The package manifest contains the following elements, arbitrarily ordered:
Zero or more xsl:expose
declarations that define the interface
offered by this package to the outside world. An xsl:expose
declaration may appear only as a child of xsl:package
.
Zero or more additional declarations.
These are the same as the declarations permitted as children of xsl:stylesheet
or xsl:transform
.
Some declarations of particular relevance to packages include:
The xsl:use-package
declaration, which declares the names and
versions of the packages on which this package is dependant.
The optional xsl:global-context-item
element; if present this
element defines constraints on the existence and type of the global context item.
Zero or more xsl:include
and xsl:import
declarations, which define additional stylesheet modules to be incorporated into this
package.
Zero or more ordinary declarations, that is,
elements that are permitted as children of xsl:stylesheet
or
xsl:transform
. One possible coding style is to include in
the package manifest just a single xsl:import
or
xsl:include
declaration as a reference to the effective
top-level stylesheet module; this approach is particularly suitable when
writing code that is required to run under earlier releases of XSLT as well as
under XSLT 3.0. Another approach is to include the substance of the top-level
stylesheet module inline within the package manifest.
The following example shows a package that offers a number of functions for manipulating complex numbers. A complex number is represented as a map with two entries, the keys being 0 for the real part, and 1 for the imaginary part.
<xsl:package name="http://example.org/complex-arithmetic.xsl" package-version="1.0" version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:f="http://example.org/complex-arithmetic.xsl"> <xsl:function name="f:complex-number" as="map(xs:integer, xs:double)" visibility="public"> <xsl:param name="real" as="xs:double"/> <xsl:param name="imaginary" as="xs:double"/> <xsl:sequence select="map{ 0:$real, 1:$imaginary }"/> </xsl:function> <xsl:function name="f:real" as="xs:double" visibility="public"> <xsl:param name="complex" as="map(xs:integer, xs:double)"/> <xsl:sequence select="$complex(0)"/> </xsl:function> <xsl:function name="f:imag" as="xs:double" visibility="public"> <xsl:param name="complex" as="map(xs:integer, xs:double)"/> <xsl:sequence select="$complex(1)"/> </xsl:function> <xsl:function name="f:add" as="map(xs:integer, xs:double)" visibility="public"> <xsl:param name="x" as="map(xs:integer, xs:double)"/> <xsl:param name="y" as="map(xs:integer, xs:double)"/> <xsl:sequence select=" f:complex-number( f:real($x) + f:real($y), f:imag($x) + f:imag($y))"/> </xsl:function> <xsl:function name="f:multiply" as="map(xs:integer, xs:double)" visibility="public"> <xsl:param name="x" as="map(xs:integer, xs:double)"/> <xsl:param name="y" as="map(xs:integer, xs:double)"/> <xsl:sequence select=" f:complex-number( f:real($x)*f:real($y) - f:imag($x)*f:imag($y), f:real($x)*f:imag($y) + f:imag($x)*f:real($y))"/> </xsl:function> <!-- etc. --> </xsl:package>
A more complex package might include private or abstract functions as well as
public functions; it might expose components other than functions (for example,
templates or global variables), and it might contain
xsl:use-package
elements to allow it to call on the services
of other packages.
Note:
In this example, the way in which complex numbers are represented is exposed to
users of the package. It would be possible to hide the representation by
declaring the types on public functions simply as item()
; but this
would be at the cost of type safety.
A package that does not itself expose any components may be written
using a simplified syntax: the xsl:package
element is omitted, and
the xsl:stylesheet
or xsl:transform
element is now
the outermost element of the stylesheet module. For compatibility reasons, all the
named templates and modes declared in the package are made public. More formally,
the
principal stylesheet module of the top-level
package may be expressed as an xsl:stylesheet
or
xsl:transform
element, which is equivalent to the package represented
by the output of the following transformation, preserving the base URI of the
source:
<xsl:transform version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:t="http://www.w3.org/1999/XSL/TransformAlias"> <xsl:namespace-alias stylesheet-prefix="t" result-prefix="xsl"/> <xsl:template match="xsl:stylesheet|xsl:transform"> <t:package declared-modes="no"> <xsl:copy-of select="@*"/> <t:expose component="mode" names="*" visibility="public"/> <t:expose component="template" names="*" visibility="public"/> <xsl:copy-of select="node()"/> </t:package> </xsl:template> </xsl:transform>
The effect of the input-type-annotations
attribute is defined in 4.4.1 Stripping Type Annotations from a Source Tree.
A more extensive example of a package, illustrating how components in a package can be overridden in a client package, is given in 3.5.7 Worked Example of a Library Package.
If a package has a version number, the version number must conform to the grammar:
PackageVersion ::= NumericPart ( "-" NamePart )? NumericPart ::= IntegerLiteral ( "." IntegerLiteral )* NamePart ::= NCName
Here IntegerLiteralXP30 and NCName
are as defined in
the XPath 3.0 grammar productions of the same name (including rules on
limits). Leading and trailing whitespace is ignored; no other
whitespace is allowed.
Examples of valid version numbers are 2.0.5
or
3.10-alpha
.
[Definition: The integer literals and the optional
NamePart
within the version number are referred to as the
portions of the version number.]
Note:
This means that 1-alpha-2
is a valid version number, with two
portions: 1
and
alpha-2
. The second hyphen is part of the NCName
,
it does not act as a portion separator.
Versions are ordered. When comparing two versions:
Trailing zero portions (that is, any zero-valued integer that is not followed by another integer) are discarded.
Comparison proceeds by comparing portions pairwise from the left.
If both versions have the same number of portions and all portions
compare equal (under the rules of the
XPath eq
operator using the Unicode codepoint
collation), then the versions compare equal.
If the number of portions in the two
versions V1 and V2 is N1 and N2,
with N1<N2, and if all portions in positions 1 to N compare equal, then
V1 is less than V2 if the portion of V2 in position N1 is an integer, and is
greater than V2 if this portion is an
NCName
. For example, 1.2
is less than
1.2.5
, while 2.0
is greater than
2.0-rc1
.
Portions are compared as follows:
If both portions are integers, they are compared using the rules of XPath value comparisons.
If both portions are NCNames, they are compared using the rules of XPath value comparisons, using the Unicode Codepoint Collation.
If one portion is an integer and the other is an
NCName
, the NCName
comes first.
For example, the following shows a possible ordered sequence of version numbers:
0-rc1 < 0-rc2 < 0 < 1 = 1.0 < 1.0.2 < 1.0.3-rc1 < 1.0.3 < 1.0.3.2 < 1.0.10
Note:
The version number format defined here is designed to be general enough to accommodate a variety of conventions in common use, and to allow useful semantics for matching of versions and ranges of versions, without being over-prescriptive. It is influenced by [SemVer], but is not as prescriptive, and it imposes no assumptions about backwards compatibility of packages between successive versions.
Implementations may impose limits on the values used in a version number (or a version range: see below). Such limits are implementation-defined. As a minimum, a processor must accept version numbers including:
A numeric part containing four integers;
Each integer being in the range 0 to 999999;
An NCName
of up to 100 characters
Dependencies between packages may specify a version range (see 3.5.2 Dependencies between Packages). A version range represents a set of accepted versions. The syntax of a version range is shown below. Whitespace is permitted only where indicated, using the terminal symbol S.
PackageVersionRange ::= AnyVersion | VersionRanges AnyVersion ::= "*" VersionRanges ::= VersionRange (S? "," S? VersionRange)* VersionRange ::= PackageVersion | VersionPrefix | VersionFrom | VersionTo | VersionFromTo VersionPrefix ::= PackageVersion ".*" VersionFrom ::= PackageVersion "+" VersionTo ::= "to" S (PackageVersion | VersionPrefix) VersionFromTo ::= PackageVersion S "to" S (PackageVersion | VersionPrefix)
The meanings of the various forms of version range are defined below:
The range AnyVersion
matches any version.
The range VersionRanges
matches a version if any constituent
VersionRange
matches that version.
For example, 9.5.0.8, 9.6.1.2
matches those specific versions only, while 9.5.0.8, 9.6+
matches either version 9.5.0.8 or any version from 9.6 onwards.
A range that is a PackageVersion
matches that version only.
The range VersionPrefix
matches any version whose leading
portions are the same as the portions in the PackageVersion
part of the
VersionPrefix
.
For example, 1.3.*
matches 1.3
,
1.3.5
, 1.3.10.2
, and
1.3-beta
(but not 1
or
1.4
).
Note:
The .*
indicates that additional portions may follow; it does not indicate a substring match
on the final portion. So
1.3.*
does not match 1.35
, and
3.3-beta.*
does not match 3.3-beta12
. Also,
3.3-beta.*
does not match 3.3-beta.5
: this
is because the last dot is not a portion separator, but is part of the
final NCName
. In fact, using .*
after a version
number that includes an NCName
portion is pointless, because
an NCName
portion can never be followed by further
portions.
The range VersionFrom
matches any version that is greater than
or equal to the version supplied.
For example 1.3+
matches
1.3
, 1.3.2
, 1.4
,
and 2.1
(but not 1.3-beta
or 1.2
).
And 1.3-beta+
matches 1.3-beta
,
1.3-gamma
, 1.3.0
, 1.4
,
and 8.0
, but not 1.3-alpha
or
1.2
.
The range VersionTo
matches any version that is less than or
equal to some version that matches the VersionPrefix
.
For example, to 4.0
matches 1.5
,
2.3
, 3.8
, 4.0
,
and 4.0-beta
(but not 4.0.1
), while to
3.3.*
matches 1.5
or 2.0.6
or
3.3.4621
, but not 3.4.0
or
3.4.0-beta
.
The range VersionFromTo
matches any version that is greater
than or equal to the starting PackageVersion
, and less than or
equal to some version that matches the VersionPrefix
.
For example, 1 to 5
matches 1.1
,
2.1
, 3.1
, or 5.0
(but
not 5.1
), while 1 to 5.*
matches all of these,
plus versions such as 5.7.2
(but not 6.0
or
6.0-beta
). Similarly,
1.0-beta to 1.0
matches 1.0-beta
,
1.0-beta.2
, 1.0-gamma
, and 1.0
,
but not 1.0-alpha
or 1.0.1
.
When components in one package reference components in another, the dependency of the first
package on the second must be represented by an xsl:use-package
element. This may appear in the principal stylesheet module
of the first package (which may be a package manifest), or
it may appear in a stylesheet module that is referenced from
the principal stylesheet module via one or more
xsl:include
declarations; however it must not be referenced
via xsl:import
declarations (this is to avoid complications
caused by multiple xsl:use-package
declarations with
different import precedence).
[Definition: If a package Q contains an
xsl:use-package
element that references package
P, then package Q is said to use package
P. In this relationship package Q is referred to as
the using package, package P as the used
package.]
The phrase directly uses is synonymous with uses as defined above, while directly or indirectly uses refers to the transitive closure of this relationship.
<!-- Category: declaration -->
<xsl:use-package
name = uri
package-version? = string >
<!-- Content: (xsl:accept | xsl:override)* -->
</xsl:use-package>
A package may be used by more than one other package, but the relationship must not be cyclic. It is possible, but by no means inevitable, that using the same package in more than one place within a stylesheet will cause static errors due to the presence of conflicting components according to the above rules. Where a package is successfully used by more than one other package, its components may be overridden in different ways by different using packages.
The name
and package-version
attributes together
identify the used package. The value of the
package-version
attribute, if present, must conform to the
rules for a PackageVersionRange
given in 3.5.1 Versions of a Package; if omitted the value *
is assumed,
which matches any version. The used package must have a name that is an exact
match for the name in the name
attribute (using codepoint
comparison), and its explicit or implicit package-version
must
match the version range given in the package-version
attribute.
This specification does not define how the implementation locates a package given its name and version. If several matching versions of a package are available, it does not define which of them is chosen. Nor does it define whether this process locates source code or some other representation of the package contents. Such mechanisms are implementation-defined. Use of the package name as a dereferenceable URI is not recommended, because the intent of the packaging feature is to allow a package to be distributed as reusable code and therefore to exist in many different locations.
[ERR XTSE3000] It is a static error if no package matching the package
name and version specified in an xsl:use-package
declaration can be located.
[ERR XTSE3005] It is a static error if a package is dependent on
itself, where package A is defined as being dependent on package
B if A contains an xsl:use-package
declaration that references B, or if A contains an
xsl:use-package
declaration that references a package
C that is itself dependent on B.
[ERR XTSE3008] It is a static error if an xsl:use-package
declaration appears in a stylesheet module that is not in the
same stylesheet level as the principal stylesheet module
of the package.
Note:
Depending on the implementation architecture, there may be a need to locate used packages both during static analysis (for example, to get information about the names and type signatures of the components exposed by the used package), and also at evaluation time (to link to the implementation of these components so they can be invoked). A failure to locate a package may cause an error at either stage.
The xsl:accept
and xsl:override
elements are
used to modify the visibility or behavior of components acquired from the used
package; they are described in 3.5.3.2 Accepting Components below.
Note:
It is not intrinsically an error to have two
xsl:use-package
declarations that identify the same package
(or different versions of the same package). This has the same effect as
having two declarations that identify packages with different names but
identical content. In most cases it will result in an error ([see ERR XTSE3050])
due to the presence of multiple components with the same name; but
no error would occur, for example, if the used package is empty, or if the
two xsl:use-package
declarations use xsl:accept
to accept non-overlapping subsets of the components in the used package.
This section discusses the use of named components in packages.
The components which can be declared in one package and referenced in another are: functions, named templates, attribute sets, modes, and global variables and parameters.
In addition, keys and accumulators are classified as named components because they can contain references to components in another package, even though they cannot themselves be referenced from outside the package.
Named and unnamed modes come within the scope of this section, but there are differences noted in 3.5.4 Overriding Template Rules from a Used Package.
Not all declarations result in components:
Named declarations that can neither be referenced from outside their
containing package, nor can contain references to components in other
packages (examples are xsl:output
,
xsl:character-map
, and
xsl:decimal-format
) are not considered to be components
and are therefore outside the scope of this section.
Some declarations, such as xsl:decimal-format
and
xsl:strip-space
, declare aspects of the processing
context which are not considered to be components as defined here.
Template rules
(xsl:template
with a match
attribute) are
also not considered to be components for the purposes of this section, which
is concerned only with components that are bound by name. However, when an
xsl:template
has both a match
attribute and
a name
attribute, then it establishes both a template rule and
a named template, and in its role
as a named template it comes within the scope of this discussion.
A named declaration, for example a named template, a function, or a global variable, may be overridden within the same package by another like-named declaration having higher import precedence. When a declaration is overridden in this way it cannot be referenced by name either from within its containing package or from outside that package.
In the case of xsl:attribute-set
and xsl:key
declarations, several declarations combine to
form a single component.
The section is largely concerned with details of the rules that affect references from one component to another by name, whether the components are in the same package or in different packages. The rules are designed to meet a number of requirements:
A component defined in one package can be overridden by a component in another package, provided the signatures are type-compatible.
The author of a package can declare whether the components in the package are public or private (that is, whether or not they can be used from outside the package) and whether they are final, overridable, or abstract (that is whether they can or must be overridden by the using package).
Within an application, two packages can make use of a common library and override its components in different ways.
Visibility of components can be defined either as part of the declaration of the component, or in the package manifest.
An application that wishes to make use of a library package can be selective about which components from the library it acquires, perhaps to avoid name clashes between components acquired from different libraries.
[Definition: The term component is used to refer to any of the following: a stylesheet function, a named template, a mode, an accumulator, an attribute set, a key, global variable, or a mode.]
[Definition: The symbolic identifier of a component is a composite name used to identify the component uniquely within a package. The symbolic identifier comprises the kind of component (stylesheet function, named template, accumulator, attribute set, global variable, key, or mode), the expanded QName of the component (namespace URI plus local name), and in the case of stylesheet functions, the arity.]
Note:
In the case of the unnamed mode, the expanded QName of the component may be considered to be some system-allocated name different from any user-defined mode name.
[Definition: Two components are said to be homonymous if they have the same symbolic identifier.]
Every component has a declaration in some stylesheet module and therefore within some package. In the case of attribute sets and keys, there may be several declarations. The declaration is an element in an XDM tree representing the stylesheet module. Declarations therefore have identity, based on XDM node identity.
[Definition: The declaring
package of a component is the
package that contains the declaration (or,
in the case of xsl:attribute-set
and
xsl:key
, multiple declarations) of the
component.]
When a component declared in one package is made available in another, the using package will contain a separate component that can be regarded as a modified copy of the original. The new component shares the same symbolic identifier as the original, and it has the same declaration, but it has other properties such as its visibility that may differ from the original.
[Definition: A
component declaration results in multiple components, one in the package in
which the declaration appears, and potentially one in each package that uses
the declaring package, directly or indirectly, subject to the visibility of the
component. Each of these multiple components has the same declaring package, but each has a different containing
package. For the original component, the declaring package and the
containing package are the same; for a copy of a component made as a result of
an xsl:use-package
declaration, the declaring package will be
the original package, and the containing package will be the package in which
the xsl:use-package
declaration appears.]
Note:
Within this specification, we generally use the notation CP for a component named C whose declaring package and containing package are both P; and the notation CPQ for a component whose containing package is P and whose declaring package is Q (that is, a component in P that is derived from a component CQ in the used package Q).
The properties of a component are as follows:
The original declaration of the component.
The package to which the component belongs (called its containing package, not to be confused with the declaring package).
The symbolic identifier of the component.
The visibility of the component,
which determines the way in which the component is seen by other components
within the same package and within using packages. This is one of
public
, private
, abstract
,
final
, or hidden
. The visibility of components
is discussed further in 3.5.3.1 Visibility of Components.
A set of bindings for the symbolic references in the component. The way in which these bindings are established is discussed further in 3.5.3.5 Binding References to Components.
Note:
When a function F defined in a package P is acquired by two using packages Q and R, we may think of P, Q, and R as all providing access to the “same” function. The detailed semantics, however, demand an understanding that there is one function declaration, but three components. The three components representing the function F within packages P, Q, and R have some properties in common (the same symbolic identifier, the same declaration), but other properties (the visibility and the bindings of symbolic references) that may vary from one of these components to another.
[Definition: The declaration of a component includes
constructs that can be interpreted as references to other components by means of their symbolic identifiers. These
constructs are generically referred to as symbolic references.
Examples of constructs that give rise to symbolic references are the
name
attribute of xsl:call-template
; the
[xsl:]use-attribute-sets
attribute of
xsl:copy
, xsl:element
, and literal result elements; the
explicit or implicit
mode
attribute of xsl:apply-templates
; XPath
variable references referring to global variables; XPath static function calls (including partial function
applications) referring to stylesheet functions; and
named function references (example: my:f#1
) referring to
stylesheet functions.
]
Symbolic references exist as properties of the declaration of a component.
The symbolic identifier being
referred to can be determined straightforwardly from the syntactic form and
context of the reference: for example, the instruction <xsl:value-of
select="f:price($o)" xmlns:f="http://f.com/"/>
contains a symbolic
reference to a function with expanded name {http://f.com/}price
and
with arity=1. However, because there may be several (homonymous) function
components with this symbolic identifier, translating this symbolic reference into
a reference to a specific component (a process called “binding”) is less
straightforward, and is described in the text that follows.
The process of assembling a stylesheet from its constituent packages is primarily a process of binding these symbolic references to actual components. Within any component whose declaration is D, there is a set of bindings; each binding is an association between a symbolic reference in D and a component whose symbolic identifier matches the outward reference. Outward references for which a component C contains a binding are said to be bound in C; those for which C contains no binding are said to be unbound.
For example, suppose that in some package Q, function A
calls B, which in turn calls C, and that B is
private
. Now suppose that in some package P which uses
Q, C is overridden. The effect of the binding process is
that P will contain three components corresponding to A,
B, and C, which we might call AP,
BP, and CP. The declarations of AP and BP are in package
Q, but the declaration of CP is in P. The
internal visibility of BP will be hidden
(meaning that it
cannot be referenced from within P), and BP will contain a
binding for the component CP that corresponds to the outward reference
from B to C. The effect is that when A calls
B and B calls C, it is the overriding version
of C that is executed.
In another package R that uses Q without overriding C, there will be three different components AR, BR, and CR. This time the declaration of all three components is in the original package Q. Component BR will contain a binding to CR, so in this package, the original version of C is executed. The fact that one package P overrides C thus has no effect on R, which does not override it.
The binding process outlined above is described in more detail in 3.5.3.5 Binding References to Components.
Template rules are not components in their own right; unlike named templates, they are never referenced by name. Component references within a template rule (for example, references to functions, global variables, or named templates) are treated as occurring within the component that represents the containing mode. This includes component references within the match patterns of template rules. If a template rule lists several modes, it is treated as if there were multiple template rules one in each mode.
An xsl:apply-templates
instruction
with no mode
attribute is treated as a reference to the default mode
defined for that instruction (see 3.7.2 The default-mode Attribute), which in turn defaults to the unnamed mode. An implicit
reference to the unnamed made is treated in the same way as any other symbolic reference. Note that there is an unnamed mode in every
package, and the unnamed mode always has private visibility.
Where an xsl:template
element has both
a name
and a match
attribute, it is treated as if there
were two separate xsl:template
elements, one with a
name
attribute and one with a match
attribute.
Keys
and accumulators behave rather differently from other
components. Their visibility is always private, which means they can only be used
within their declaring package. In addition, the component binding is generally
made dynamically rather than statically, by
virtue of a string passed as an argument to the function
key
, accumulator-before
, or
accumulator-after
. (In the case of accumulators, there
can also be static references: see the use-accumulators
attribute
of xsl:source-document
,
xsl:merge-source
, and xsl:mode
.)
However, outward references from key
definitions and accumulators to other components (such as global
variables and functions) behave in the same way as component references contained
in any other private component, in that they may be re-bound to an overriding
declaration of the target component.
[Definition: The visibility of a
component is one of:
private
, public
, abstract
,
final
, or hidden
.]
The meanings of these visibility values is as follows:
The component can be referenced from other components in this package or in any using package; it can be overridden by a different component in any using package.
The component can be referenced from other components in this package; it cannot be referenced or overridden within a using package.
The component can be referenced from other components in this package or in any using package; in a using package it can either remain abstract or be overridden by a different component.
The component can be referenced from other components in this package or in any using package; it cannot be overridden by a different component in any using package.
The component cannot be referenced from other components in this package; it cannot be referenced or overridden within a using package.
Note:
The visibility of a component in a package P primarily affects
how the component can be used in other packages, specifically, packages that
use P. There is one exception: if the visibility is
hidden
, it also affects how the component can be used within
P.
When a component is declared within a particular
package, its visibility, which affects
how it can be used in other (using) packages, depends on two factors: the value
of the visibility
declaration on the declaration itself (if
present), and the rules given in the xsl:expose
declarations
of the package manifest.
The xsl:function
, xsl:template
,
xsl:attribute-set
, xsl:variable
,
and
xsl:mode
declarations each have an optional
visibility
attribute. The value is one of private
,
public
, abstract
, or final
(never
hidden
). In the case of
an xsl:param
element there is no explicit
visibility
attribute; rather the declaration has the
implicit attribute visibility="public"
.
Any xsl:expose
declarations that
appear as children of xsl:package
define the visibility of
components whose declaration has no explicit visibility
attribute,
and can also be used to reduce the visibility of components where this
attribute is present.
<xsl:expose
component = "template" | "function" | "attribute-set" | "variable" | "mode" | "*"
names = tokens
visibility = "public" | "private" | "final" | "abstract" />
The xsl:expose
element allows the visibility of selected components within a package to be defined.
The components in question are identified using their symbolic identifiers. The
component
attribute defines the kind of component that is
selected.
The value *
means “all component kinds”;
in this case the value of the names
attribute must be a WildcardXP30.
An xsl:expose
declaration has no effect on the
unnamed mode, which is always private to a package.
The names
attribute selects a subset of these components by name
(and in the case of functions, arity); its value is a whitespace-separated
sequence of tokens each of which is either a NameTestXP30 or a NamedFunctionRefXP30. (Examples are
*
, p:*
, *:local
,
p:local
, and p:local#2
.)
The value may be a NamedFunctionRef
only in the case of stylesheet
functions, and distinguishes functions with the same name and different
arity.
The visibility of a named template, function, variable, attribute set, or mode declared within a package is the first of the following that applies, subject to consistency constraints which are defined below:
The visibility of a variable declared using
an xsl:param
element is
always public
. No xsl:expose
element
ever matches an xsl:param
component.
Note:
Attempting to match an xsl:param
with
an explicit EQName
will therefore always give an error, while
using a wildcard has no effect.
If the package manifest contains an xsl:expose
element
that matches this component by virtue of an explicit EQName
or NamedFunctionRef
(that is, not by virtue of a wildcard
match), then the value of the visibility
attribute of the
last such xsl:expose
element in document order (call
this the explicit exposed visibility).
If the declaration of the component has a visibility
attribute, then the value of this attribute (call this the declared
visibility).
If the package manifest contains an xsl:expose
element
that matches this component by virtue of a wildcard match that specifies
either the namespace part of the component name or the local part of the
name (for example, prefix:*
or *:local
or
Q{uri}*
), then the value of the visibility
attribute of the last such xsl:expose
element in
document order.
If the package manifest contains an xsl:expose
element
that matches this component by virtue of a wildcard match that matches
all names (that is, *
), then the value of the
visibility
attribute of the last such
xsl:expose
element in document order.
Otherwise, private
.
Note:
In the above rules, no distinction is made between declarations that specify
a specific component kind, and those that specify component="*"
. If both match,
the value of the component
attribute plays no role in deciding which
declaration wins.
If both a declared visibility and an explicit
exposed visibility exist for the same component, then as mentioned above, they
must be consistent. This is determined by reference to the following table,
where the entry N/P means “not permitted”. (In cases where the combination is
permitted, the actual visibility is always the same as the visibility
determined by xsl:expose
.)
Explicit exposed visibility | Declared visibility | |||
---|---|---|---|---|
public | private | final | abstract | |
public | public | N/P | N/P | N/P |
private | private | private | private | N/P |
final | final | N/P | final | N/P |
abstract | N/P | N/P | N/P | abstract |
[ERR XTSE3010] It is a static error if the
explicit exposed visibility of a component is inconsistent with its
declared visibility, as defined in the above table. (This error occurs
only when the component declaration has an explicit
visibility
attribute, and the component is also listed
explicitly by name in an xsl:expose
declaration.)
[ERR XTSE3020] It is a static error if a token
in the names
attribute of xsl:expose
, other
than a wildcard, matches no component in the containing package.
[ERR XTSE3022] It is a static error if the
component
attribute of xsl:expose
specifies *
(meaning all component kinds) and the names
attribute is not a wildcard.
Note:
There is no ambiguity, and no error, if several tokens within the same
xsl:expose
element match the same component.
If the visibility of a component as established by the above rules
is abstract
, then the component must have a declared visibility of abstract
.
Note:
In other words, the xsl:expose
declaration cannot be used to make a component
abstract unless it was declared as abstract to start with.
[ERR XTSE3025] It is a static error if the
effect of an xsl:expose
declaration would be to make a component
abstract
, unless the component is already abstract
in the absence of the xsl:expose
declaration.
For a component accepted into a package P
from another package Q, the visibility of the component in P (which primarily
affects how it can be used in a package R that uses P)
depends on the visibility declared in the relevant xsl:accept
or xsl:override
element in P (see 3.5.3.2 Accepting Components); this in turn has a default that depends on
the visibility of the corresponding component in Q. In this case the
visibility is unaffected by any xsl:expose
declaration in
P.
When a package P uses a package Q, by virtue of an
xsl:use-package
element in the package manifest of P, then
P will contain a component
corresponding to every component in Q. The visibility of the component within
P depends on the visibility of the component in Q, optionally modified
by two elements that may appear as children of the
xsl:use-package
element, namely xsl:accept
and xsl:override
.
For every component CQ in package Q that is not matched
by any xsl:override
or xsl:accept
element in
the package manifest of P, there will be a corresponding component
CP in package P that has the same symbolic identifier and declaration as CQ.
If CQ is an xsl:param
component, then the visibility of CP is
public
.
In other cases, the visibility of CP depends on the visibility of CQ, as defined by the following table:
Visibility in used package CQ | Visibility in using package CP |
---|---|
public | private |
final | private |
private | hidden |
hidden | hidden |
abstract | hidden |
Note:
The effect of these rules is as follows:
Components that are public or final in the used package Q become private in the using package P. This means that they can be referenced within P but are not (by default) visible within a package R that uses P.
Components that are private or hidden in the used package Q become hidden in the using package P. This means that they cannot be referenced within P; but if they contain references to components that are overridden in P, the hidden component’s references are bound to the overriding components in P.
Components that are abstract in the used package Q become hidden in the using package P. The hidden component in this case raises a dynamic error if it is invoked. Such an invocation cannot originate within P, because the component is not visible within P; but it can occur if a public component in Q is invoked, which in turn invokes the abstract component.
<xsl:accept
component = "template" | "function" | "attribute-set" | "variable" | "mode" | "*"
names = tokens
visibility = "public" | "private" | "final" | "abstract" | "hidden" />
The xsl:accept
element has very similar syntax and semantics
to xsl:expose
. Whereas xsl:expose
allows a
package to restrict the visibility of its own components to other (using)
packages, xsl:accept
allows a package to restrict the
visibility of components exposed by a package that it uses. This may be
necessary if, for example, it uses two different packages whose component names
conflict. It may also simply be good practice if the package author knows that
only a small subset of the functionality of a used package is required.
The rules for determining whether an xsl:accept
element
matches a particular component, and for which element to use if there are
several matches, are the same as the rules for the xsl:expose
element.
No xsl:accept
element
ever matches a variable declared using xsl:param
.
Note:
Attempting to match an xsl:param
with
an explicit EQName
will therefore always give an error, while
using a wildcard has no effect.
[ERR XTSE3030] It is a static error if a token
in the names
attribute of xsl:accept
, other
than a wildcard, matches no component in the used package.
[ERR XTSE3032] It is a static error if the
component
attribute of xsl:accept
specifies *
(meaning all component kinds) and the names
attribute is not a wildcard.
In the absence of a matching xsl:override
element (see
3.5.3.3 Overriding Components from a Used Package), the visibility of a component that matches an
xsl:accept
element depends both on the
visibility
attribute of the best-matching
xsl:accept
element and on the visibility of the corresponding component in the used package,
according to the following table. In this table the entry “N/P” means “not
permitted”.
Visibility in xsl:accept element
|
Visibility in used package | |||
---|---|---|---|---|
public | private | final | abstract | |
public | public | N/P | N/P | N/P |
private | private | N/P | private | N/P |
final | final | N/P | final | N/P |
abstract | N/P | N/P | N/P | abstract |
hidden | hidden | N/P | hidden | hidden |
[ERR XTSE3040] It is a static error if the
visibility assigned to a component by an xsl:accept
element is incompatible with the visibility of the corresponding
component in the used package, as defined by the above table, unless the
token that matches the component name is a wildcard, in which case the
xsl:accept
element is treated as not matching that
component.
[ERR XTSE3050] It is a static error if the
xsl:use-package
elements in a package manifest cause two or more
homonymous components to be
accepted with a visibility other than hidden
.
Conflicts between the components accepted from used packages and those declared within the package itself are handled as follows:
If the conflict is between two components both declared within the package itself, then it is resolved by the rules relating to import precedence defined for each kind of component.
If the conflict is between two components both accepted from used packages, or between a component declared within the package and an accepted component, then a static error occurs.
If a component is explicitly accepted from a used package (by name, rather
than by a matching wildcard), and if the same component is the subject
of an xsl:override
declaration, then a static error
occurs (see below). There is no conflict, however, if a component declared
within xsl:override
also matches a wildcard in an xsl:accept
element.
[ERR XTSE3051] It is a static error if
a token in the names
attribute of xsl:accept
,
other than a wildcard, matches the symbolic name of a component declared
within an xsl:override
child of the same
xsl:use-package
element.
Where the used package Q contains a component whose
visibility is abstract
, the using package P has three options:
P can accept the component with visibility="abstract"
.
In this case P can contain references to the component, but invocation via
these references will fail unless a non-abstract overriding component has
been supplied in some package R that (directly or indirectly) uses P.
P can accept the component with visibility="hidden"
.
In this case P cannot contain references to the component, and invocation via
references in Q will always fail with a dynamic error. This is the default
if P does not explicitly accept or override the component.
P can provide a concrete implementation of the component
within an xsl:override
element.
Any invocation of the absent component (typically from within its declaring package) causes a dynamic error, as if the component were overridden by a component that unconditionally raises a dynamic error.
[ERR XTDE3052] It is a dynamic error if an invocation of an abstract component is evaluated.
Note:
This can occur when a public component in the used package invokes
an abstract component in the used package, and the using package provides
no concrete implementation for the component in an xsl:override
element.
Note:
To override a component accepted from a used package, the overriding
declaration must appear as a child of the xsl:override
element.
Note:
There is no rule that prevents a function (say) being declared in the using
package with the same name as a private
function in the used
package. This does not create a conflict, since all references in the used
package are bound to one function and all those in the using package are
bound to another.
[Definition: A component in a using package may
override a component in a used package, provided that the
visibility of the component in the
used package is either abstract
or public
. The
overriding declaration is written as a child of the
xsl:override
element, which in turn appears as a child
of xsl:use-package
.]
<xsl:override>
<!-- Content: (xsl:template | xsl:function | xsl:variable | xsl:param | xsl:attribute-set)* -->
</xsl:override>
Note:
This mechanism is distinct from the mechanism for overriding declarations within the same package by relying on import precedence. It imposes stricter rules: the overriding component is required to be type-compatible with the component that it overrides.
If the used package Q contains a component
CQ and the xsl:use-package
element contains an
xsl:override
element which contains a declaration
D whose symbolic
identifier matches the symbolic identifier of CQ, then
the using package P will contain a component CP whose
declaration is D, whose symbolic identifier is that of D, and whose visibility is equal to the value of the visibility
attribute of D, or private
if this is absent,
except in the case
of xsl:param
, which is implicitly
public
.
The using package P will also contain a component CPQ
whose body is the same as the body of CQ and whose visibility is hidden
. This
component is used as the target of a binding for the symbolic reference
xsl:original
described below.
Other than its appearance as a child of xsl:override
, the
overriding declaration is a normal xsl:function
,
xsl:template
, ,
xsl:variable
, xsl:param
, or
xsl:attribute-set
element. In the case of
xsl:variable
and xsl:param
, the variable
that is declared is a global
variable.
The rules in the remainder of this section apply to
components having a name
attribute (named
components). The only element with no name
attribute that
can appear as a child of xsl:override
is an
xsl:template
declaration having a match
attribute (that is, a template rule). The rules for
overriding of template rules appear in 3.5.4 Overriding Template Rules from a Used Package. If
an xsl:template
element has both a name
attribute
and a match
attribute, then it defines both a named component and
a template rule, and both sections apply.
[ERR XTSE3055] It is a static error if a
component declaration appearing as a child of
xsl:override
is homonymous with any other declaration in the using package,
regardless of import
precedence, including any other overriding declaration in
the package manifest of the using package.
Note:
When an attribute set is overridden, the
overriding attribute set must be defined using a single
xsl:attribute-set
element. Attribute sets defined in
different packages are never merged by virtue of having the same name,
though they may be merged explicitly by using the
use-attribute-sets
attribute.
[ERR XTSE3058] It is a static error if a
component declaration appearing as a child of
xsl:override
does not match (is not homonymous with) some component in the
used package.
[ERR XTSE3060] It is a static error if the
component referenced by an xsl:override
declaration has
visibility other than
public
or abstract
A package is executable if and only if it contains no component whose visibility is abstract
. A package that is not
executable is not a stylesheet, and
therefore cannot be nominated as the stylesheet to be used when initiating a
transformation.
Note:
In other words, if a component is declared as abstract, then some package that uses the declaring package of that component directly or indirectly must override that component with one that is not abstract. It is not necessary for the override to happen in the immediately using package.
[ERR XTSE3070] It is a static error if the signature of an overriding component is not compatible with the signature of the component that it is overriding.
[Definition: The signatures of two components are compatible if they present the same interface to the user of the component. The additional rules depend on the kind of component.]
Compatibility is only relevant when comparing two components that have the same symbolic identifier. The compatibility rules for each kind of component are as follows:
Two attribute sets with the same name are compatible if and only if they satisfy the following rule:
If the overridden attribute set specifies
streamable="yes"
then the overriding attribute set
also specifies streamable="yes"
.
Two functions with the same name and arity are compatible if and only if they satisfy all the following rules:
The declared types of the arguments
(defaulting to item()*
) are pairwise identical.
The declared return types
(defaulting to item()*
) are identical.
The effective value of the
new-each-time
attribute on the overriding function is the same as its value on the overridden function.
If the overridden function specifies
streamable="yes"
then the overriding function also
specifies streamable="yes"
, and in addition, it has
the same posture and sweep
as the function that it overrides.
Two named templates with the same name are compatible if and only if they satisfy all the following rules:
Their return types are identical.
For every non-tunnel parameter on the overridden template, there is a
non-tunnel parameter on the overriding template that has the same name, an
identical required
type, and the same effective value for the required
attributes.
For every tunnel parameter P on the overridden template, if there is a parameter Q on the overriding template that has the same name as P then Q is also a tunnel parameter, and P and Q have identical required types.
Any parameter on the overriding template for which there is no
corresponding parameter on the overridden template specifies
required="no"
.
The two templates have equivalent
xsl:context-item
children, where equivalence
means that the use
attributes are the same and the
required types are identical; an absent
xsl:context-item
is equivalent to one that
specifies use="optional"
and
as="item()"
.
Two variables (including parameters) with the same name are compatible if and only if they satisfy all the following rules:
Their declared types are identical.
Note:
A variable may override a parameter or vice-versa, and the initial value may differ.
Because static variables and parameters are
constrained to have visibility private
,
they cannot be overridden in another package. The compatibility rules
therefore do not arise. The reason that such variables cannot be
overridden is that they are typically used during stylesheet
compilation (for example, in [xsl:]use-when
expressions
and shadow attributes) and it is a design goal that packages should be
capable of independent compilation.
[Definition: Types S and T are considered identical for the purpose of
these rules if and only if subtype(S, T)
and subtype(T,
S)
both hold, where the subtype relation is defined in Section
2.5.6.1 The judgement subtype(A, B)
XP30.]
Note:
One consequence of this rule is that two plain union types are considered identical if they have the same set of member types, even if the union types have different names or the ordering of the member types is different.
Consider a function that accepts an argument
whose declared type is a union type with member types xs:double
and xs:decimal
, in that order (we might write this as union(xs:double, xs:decimal)
).
Using the same notation, this can be overridden by a function that declares the argument
type as union(xs:decimal, xs:double)
. This does not affect type checking:
a function call that passes the type checking rules with one signature will also pass
the
type checking rules with the other. It does however affect the way that the function
conversion rules work: a call that passes the xs:untypedAtomic
value
"93.7"
(or an untyped node with this as its string value) will be converted to
an xs:decimal
in one case and an xs:double
in the other.
While this rule may appear formal, it is not as straightforward as might be supposed, because the subtype relation in XPath has a dependency on the “Type derivation OK (Simple)” relation in XML Schema, which itself appeals to a judgement as to whether the two type definitions being compared “are the same type definition”. Both XSD 1.0 and XSD 1.1 add the note “The wording of [this rule] appeals to a notion of component identity which is only incompletely defined by this version of this specification.” However, they go on to say that component identity is well defined if the components are named simple type definitions, which will always apply in this case. For named atomic types, the final result of these rules is that two atomic types are identical if and only if they have the same name.
Modes are not overridable, so the xsl:mode
declaration cannot
appear as a child of xsl:override
.
Within the declaration of an overriding named component
(that is, a component whose declaration is a child of
xsl:override
, and has a name
attribute), where
the overridden component has public visibility, it is
possible to use the name xsl:original
as a symbolic reference to
the overridden component. More specifically:
Within a named template appearing as a child of
xsl:override
, the name xsl:original
may appear as the value of the name
attribute of
xsl:call-template
: for example,
<xsl:call-template name="xsl:original"/>
.
Within a stylesheet function appearing as a child of
xsl:override
, the static context for contained XPath
expressions (other than static
expressions) is augmented as follows: the statically
known function signatures includes a mapping from the name
xsl:original
to the signature of the overridden
function (which is the same as the signature of the overriding function).
This means that the name xsl:original
can be used in static
function calls, including calls that use partial function application
(where one of the arguments is given as "?"), and also in named function
references. For example: xsl:original($x)
,
xsl:original($x, ?)
, xsl:original#2
.
Note:
The result of calling function-name(xsl:original#2)
is
the name of the overridden function, not
xsl:original
.
Neither xsl:original
, nor the overridden function, is added
to the named functions component of the dynamic context for
XPath expressions within the overriding function. This means that any
attempt to bind the function name xsl:original
dynamically
(for example using function-lookup
FO30, or
function-available
, or
xsl:evaluate
) will fail, and any attempt to bind
the name of the overriding/overridden function dynamically will return
the overriding function.
Within a global variable or parameter appearing as a
child of xsl:override
, the static context for contained
XPath expressions (other than static
expressions) is augmented as follows: the in-scope
variables includes a mapping from the name
xsl:original
to the declared type of the overridden
variable or parameter (which is the same as the type of the overriding
global variable or parameter).
Within an attribute set appearing as a child of
xsl:override
, any
[xsl:]use-attribute-sets
attribute (whether on the
xsl:attribute-set
element itself, or on any
descendant element) may include the name xsl:original
as a
reference to the overridden attribute set.
Within the overriding component CP, the symbolic reference
xsl:original
is bound to the hidden component CPQ
described earlier, whose body is that of the component CQ in the
used package.
[ERR XTSE3075] It is a static error to use the
component reference xsl:original
when the overridden
component has visibility="abstract"
.
Modes are not overridable, so the name
xsl:original
cannot be used to refer to a mode (for example in the mode
attribute of
xsl:apply-templates
).
Note:
In the case of variables, templates, and attribute sets, the invocation of the overridden component can occur only within the lexical scope of the overriding component. With functions, however, there is greater flexibility. The overriding component can obtain a reference to the overridden component in the form of a function item, and can export this value by passing it to other functions or returning it in its result. A dynamic invocation of this function item (and hence, of the overridden function) can thus occur anywhere.
[Definition: The process of identifying the component to which a symbolic reference applies (possibly chosen from several homonymous alternatives) is called reference binding.]
The process of reference binding in the presence of overriding declarations is best illustrated by an example. The formal rules follow later in the section.
Consider a package Q defined as follows:
<xsl:package name="Q" version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:variable name="A" visibility="final" select="$B + 1"/> <xsl:variable name="B" visibility="private" select="$C * 2"/> <xsl:variable name="C" visibility="public" select="22"/> </xsl:package>
(The process is illustrated here using variables as the components, but the logic would be the same if the example used functions, named templates, or attribute sets.)
There are three components in this package, and their properties are illustrated in the following table. (The ID column is an arbitrary component identifier used only for the purposes of this exposition.)
ID | Symbolic Name | Declaring Package | Containing Package | Visibility | Body | Bindings |
---|---|---|---|---|---|---|
AQ | variable A | Q | Q | final | $B + 1 |
$B → BQ |
BQ | variable B | Q | Q | private | $C * 2 |
$C → CQ |
CQ | variable C | Q | Q | public | 22 |
none |
Now consider a package P that uses Q, and that overrides one of the variables declared in Q:
<xsl:package name="P" version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:use-package name="Q"> <xsl:override> <xsl:variable name="C" visibility="private" select="$xsl:original + 3"/> </xsl:override> </xsl:use-package> <xsl:template name="T" visibility="public"> <xsl:value-of select="$A"/> </xsl:template> </xsl:package>
Package P has five components, whose properties are shown in the following table:
ID | Symbolic Name | Declaring Package | Containing Package | Visibility | Body | Bindings |
---|---|---|---|---|---|---|
APQ | variable A | Q | P | final | $B + 1 |
$B → BPQ |
BPQ | variable B | Q | P | hidden | $C * 2 |
$C → CP |
CPQ | variable C | Q | P | hidden | 22 |
none |
CP | variable C | P | P | private | $xsl:original + 3 |
$xsl:original → CPQ |
TP | template T | P | P | public | value-of select="$A |
$A → APQ |
The effect of these bindings is that when template T is called,
the result is 51
. This is why:
The result of T is the value of APQ.
The value of APQ is the value of BPQ plus 1.
The value of BPQ is the value of CP times 2.
The value of CP is the value of CPQ plus 3.
The value of CPQ is 22.
So the final result is ((22 + 3) * 2) + 1
In this example, the components of P are established in three different ways:
Components APQ, BPQ, and CPQ are modified copies of the corresponding component AQ, BQ, and CQ in the used package Q. The properties of these components are modified as follows:
The symbolic identifier, declaring package, and body are unchanged.
The containing package is changed to P.
The visibility is changed according to the
rules in 3.5.3.2 Accepting Components: in particular,
visibility="private"
changes to
visibility="hidden"
.
The references to other components are rebound as described in this section.
Component CP is the overriding component. Its properties
are exactly as if it were declared as a top-level component in
P (outside the xsl:use-package
element), except that (a) it must adhere to the constraints on
overriding components (see 3.5.3.3 Overriding Components from a Used Package), (b) it is allowed to use
the variable reference $xsl:original
, and (c) the fact
that it overrides CQ affects the way that references from
other components are rebound.
Component TP is a new component declared locally in P.
The general rules for reference binding can now be stated:
If the containing package of a component CP is P, then all symbolic references in CP are bound to components whose containing package is P.
When a package P uses a package Q, then for every component CQ in Q, there is a corresponding component CP in P, as described in 3.5.3.2 Accepting Components.
Given a component CP whose containing package and declaring package are the same package P, then (as a consequence of rules
elsewhere in this specification) for every symbolic reference
D within CP, other than a reference using the name
xsl:original
, there will always be exactly one non-hidden
component DP whose containing package is P and
whose symbolic identifier matches D
(otherwise a static error will have been reported). The reference is then
bound to DP.
In the case of a component reference using the name
xsl:original
, this will in general appear within a
component CP that overrides a component CQ whose
corresponding component in P is CPQ, and the
xsl:original
reference is bound to CPQ.
Given a component CP whose containing package
P is a different package from its declaring package
R (that is, CP is present in P by
virtue of an xsl:use-package
declaration referencing
package Q, which may or may not be the same as R),
then the component bindings in CP are derived from the
component bindings in the corresponding component CQ as
follows: if the component binding within CQ is to a component
DQ, then:
If DQ is overridden within P by a component DP, then the reference is bound to DP;
Otherwise, the reference is bound to the component DPQ in P whose corresponding component in Q is DQ.
When reference resolution is performed on a package that is intended to be used
as a stylesheet (that is, for the
top-level package), there must
be no symbolic references referring to components whose visibility is
abstract
(that is, an implementation must be provided for every
abstract component).
[ERR XTSE3080] It is a static error if a
top-level package (as
distinct from a library
package) contains
components whose visibility is abstract
.
Note:
This means that abstract components must either be overridden in a using
package by a component that supplies a real implementation, or they
must be accepted with visibility="hidden"
(see 3.5.3.2 Accepting Components), which has the effect that any invocation
of the component raises a dynamic error.
Note:
Unresolved references are allowed at the module level but not at the package level. A stylesheet module can contain references to components that are satisfied only when the module is imported into another module that declares the missing component.
Note:
The process of resolving references (or linking) is critical to an implementation that uses separate compilation. One of the aims of these rules is to ensure that when compiling a package, it is always possible to determine the signature of called functions, templates, and other components. A further aim is to establish unambiguously in what circumstances components can be overridden, so that compilers know when it is possible to perform optimizations such as inlining of function and variable references.
Suppose a public template T calls a private function F. When the package containing these two components is referenced by a using package, the template remains public, while the function becomes hidden. Because the function becomes hidden, it can no longer conflict with any other function of the same name, or be overridden by any other function; at this stage the compiler knows exactly which function T will be calling, and can perform optimizations based on this knowledge.
The mechanism for resolving component references described in this section is consistent with the mechanism used for binding function and variable references described in the XPath specification. XPath requires these variable and function names to be present in the static context for an XPath expression. XSLT ensures that all the non-hidden functions, global variables, and global parameters in a package are present in the static context for every XPath expression that appears in that package, along with required information such as the type of a variable and the signature of a function.
Named component references within inline functions follow the standard rules, but the rules need to be interpreted with care. Suppose that in package P we find the declarations:
<xsl:variable name="v" as="xs:integer" visibility="public" select="3"/> <xsl:function name="f:factory" as="function(*)" visibility="final"> <xsl:sequence select="function() {$v}"/> </xsl:function>
and that in a using package Q we find:
<xsl:use-package name="P"> <xsl:override> <xsl:variable name="v" as="xs:integer" select="4"/> </xsl:override> </xsl:use-package> <xsl:template name="xsl:initial-template"> <v value="{f:factory()()}"/> </xsl:template>
The correct output here is <v value="4"/>
.
The explanation for this is as follows. Package Q contains a function f:factoryQP
whose declaring package is P and whose containing package is Q. The symbolic reference
$v
within the body of this function is resolved in the normal way; since the containing
package
is Q, it is resolved to the global variable vQ: that is, the overriding declaration
of $v
that appears within the xsl:override
element within package Q,
whose value is 4.
In terms of internal implementation, one way of looking at this is that the anonymous
function returned
by f:factory
contains within its closure bindings for the global variables and functions that
the anonymous function references; these bindings are inherited from the component
bindings of the
component that lexically contains these symbolic references, which in this case is
f:factory
,
and more specifically the version of the f:factory
component in package Q.
There are several functions in which a dynamically-evaluated QName is used to
identify a component: these include key
,
accumulator-before
,
accumulator-after
,
function-lookup
FO30, and
function-available
. Dynamic references can also occur
in the XPath expression supplied to the xsl:evaluate
instruction.
In all these cases, the set of components that are available to be referenced
are those that are declared in the package where this function call appears,
including components declared within an xsl:override
declaration in that package, but excluding components declared with
visibility="abstract"
. If the relevant component has been
overridden in a different package, the overriding declarations are not
considered.
If one of these functions (for example key
or
accumulator-before
) is invoked via a dynamic function
invocation, then the relevant package is the one in which the function item is
created (using a construct such as key#2
, key('my-key',
?)
, or function-lookup($KEYFN, 2)
). Function items
referring to context-dependent functions bind the context at the point where
the function item is created, not the context at the point where the function
item is invoked.
Note:
This means that if a package wishes to make a key available for use by a
calling package, it can do so by creating a public global variable whose
value is a partial application of the key
function:
<xsl:variable name="get-order" select="key('orders-key', ?, ?)"/>
which the calling code can invoke as $get-order('123-456', /)
.
The rules in the previous section apply to named components including functions, named templates, global variables, and named attribute sets. The rules for modes, and the template rules appearing within a mode, are slightly different.
The unnamed mode is local to a package: in effect, each package has its own
private unnamed mode, and the unnamed mode of one package does not interact with
the unnamed mode of any other package. An
xsl:apply-templates
instruction with no mode
attribute is treated as a symbolic reference to the default
mode defined for that instruction (see 3.7.2 The default-mode Attribute), which in
turn defaults to the unnamed mode. Because the unnamed mode
always has private visibility, it cannot be overridden in another
package.
A named mode may be declared in an xsl:mode
declaration as being
either public
, private
, or final
. The
values of the visibility
attribute are interpreted as follows:
Value | Meaning |
---|---|
public | A using package may use
xsl:apply-templates to invoke templates in this mode;
it may also declare additional template rules in this mode, which are
selected in preference to template rules in the used package. These may
appear only as children of the xsl:override element
within the xsl:use-package element.
|
private | A using package may neither reference the mode nor provide additional templates in this mode; the name of the mode is not even visible in the using package, so no such attempt is possible. The using package can use the same name for its own modes without risk of conflict. |
final | A using package may use
xsl:apply-templates to invoke templates in this mode,
but it must not provide additional template rules in this mode.
|
As with other named components, an xsl:use-package
declaration
may contain an xsl:accept
element to control the visibility of a
mode acquired from the used package. The allowed values of its
visibility
attribute are public
,
private
, and final
.
The xsl:mode
declaration itself must not be overridden. A using
package must not contain an xsl:mode
declaration whose name
matches that of a public
or final
xsl:mode
component accepted from a used package.
The xsl:expose
and xsl:accept
elements may be
used to reduce the visibility of a mode in a using package; the same rules apply
in general, though some of the rules are not applicable because, for example,
modes cannot be abstract
.
It is not possible for a package to combine the template rules from two other
packages into a single mode. When xsl:apply-templates
is used
without specifying a mode, the chosen template rules will always come from the
same package; when it is used with a named mode, then they will come from the
package where the mode is defined, or any package that uses that package and adds
template rules to the mode. If two template rules defined in different packages
match the same node, then the rule in the using package wins over any rule in the
used package; this decision is made before taking other factors such as import
precedence and priority into account.
A static error occurs if two modes with the same name are visible within a package, either because they are both declared within the package, or because one is declared within the package and the other is acquired from a used package, or because both are accepted from different used packages.
The rules for matching template rules by import precedence and priority operate as
normal, with the addition that template rules declared within an
xsl:use-package
element have higher precedence than any
template rule declared in the used package. More specifically, given an xsl:apply-templates
instruction
in package P, naming a mode M that is declared in a used
package Q and is overridden in P, the search order for
template rules is:
Rules declared within P (specifically,
xsl:template
rules declared as children of an
xsl:override
element within the
xsl:use-package
element that references package
Q). If there are multiple rules declared within P
that match a selected node, they are resolved on the basis of their explicit
or implicit priority, and if the priorities are equal, the last one in declaration order wins.
Rules declared within Q, taking import precedence, priority, and declaration order into account in the usual way (see 6.4 Conflict Resolution for Template Rules).
Built-in template rules (see 6.7 Built-in Template Rules) selected
according to the on-no-match
attribute of the
xsl:mode
declaration (in Q), or its
default.
If the mode is overridden again in a package R that uses P, then this search order is extended by adding R at the start of the search list, and so on recursively.
Note:
If existing XSLT code has been written to use template rules in the unnamed
mode, a convenient way to incorporate this code into a library package is to add a stub module
that defines a new named public
or final
mode, in
which there is a single template rule whose content is the single instruction
<xsl:apply-templates select="."/>
. This in effect redirects
xsl:apply-templates
instructions using the named mode to
the rules defined in the unnamed mode.
In previous versions of XSLT, modes were implicitly declared by simply using a
mode name in the mode
attribute of xsl:template
or xsl:apply-templates
. XSLT 3.0 introduces the ability to
declare a mode explicitly using an xsl:mode
declaration (see
6.6.1 Declaring Modes).
By default, within a package that is defined using an explicit
xsl:package
element, all modes must be explicitly declared.
In an implicit package, however (that is, one rooted at an
xsl:stylesheet
or xsl:transform
element),
modes can be implicitly declared as in previous XSLT versions.
The declared-modes
attribute of xsl:package
determines whether or not modes that
are referenced within the package must be explicitly declared.
If the value is yes
(the default),
then it is an error to use a mode name
unless the package either contains
an explicit xsl:mode
declaration for that mode, or accepts the mode
from a used package. If the value is no
, then this is not an error.
This attribute affects all modules making up the package, it is not confined to
declarations appearing as children of the xsl:package
element.
[ERR XTSE3085] It is a static error,
when the effective value of the declared-modes
attribute of
an xsl:package
element is yes
, if the
package contains an explicit reference to an undeclared mode, or if
it implicitly uses the unnamed mode and the unnamed mode is undeclared.
For the purposes of the above rule:
A mode is declared if either of the following conditions is true:
The package contains an xsl:mode
declaration for that mode.
The mode is a public or final mode accepted from a used package.
The offending reference may be either an explicit mode name, or the token #unnamed
treated as a reference to the unnamed mode, or a defaulted mode attribute, and it
may occur in any of the following:
The mode
attribute of an xsl:template
declaration
The mode
attribute of an xsl:apply-templates
instruction
An [xsl:]default-mode
attribute.
A package implicitly uses the unnamed mode if either of the following conditions is true:
There is an xsl:apply-templates
element with no mode
attribute, and with no ancestor-or-self having
an [xsl:]default-mode
attribute.
There is an xsl:template
element with a match
attribute and no mode
attribute, and with no ancestor-or-self having
an [xsl:]default-mode
attribute.
The xsl:import
and
xsl:include
declarations are local to a package.
Declarations of keys, accumulators,
decimal formats, namespace aliases (see
11.1.4 Namespace Aliasing), output definitions, and character
maps within a package have local scope within that package —
they are all effectively private. The elements that declare these constructs do
not have a visibility
attribute. The unnamed decimal format and the
unnamed output format are also local to a package.
If xsl:strip-space
or xsl:preserve-space
declarations appear within a library
package, they only affect calls to the doc
FO30 or
document
functions appearing within that package. Such a declaration within the top-level package additionally affects stripping of whitespace in
the document that contains the global context item.
An xsl:decimal-format
declaration within a package applies only
to calls on format-number
FO30 appearing within that
package.
An xsl:namespace-alias
declaration within a package applies only
to literal result elements within the same package.
An xsl:import-schema
declaration within a package adds the names
of the imported schema components to the static context for that package only;
these names are effectively private, in the sense that they do not become
available for use in any other packages. However, the names of schema components
must be consistent across the stylesheet as a whole: it is not possible for two
different packages within a stylesheet to use a type-name such as part-number
to
refer to different schema-defined simple or complex types.
Type names used in the interface of public components in a package (for example, in the arguments of a function) must be respected by callers of those components, in the sense that the caller must supply values of the correct type. Often this will mean that the using component, if it contains calls on such interfaces, must itself import the necessary schema components. However, the requirement for an explicit schema import applies only where the package contains explicit use of the names of schema components required to call such interfaces.
Note:
For example, suppose a library
package contains a function which requires an argument of type
mfg:part-number
. The caller of this function must supply an
argument of the correct type, but does not need to import the schema unless it
explicitly uses the schema type name mfg:part-number
. If it
obtains an instance of this type from outside the package, for example as the
result of another function call, then it can supply this instance to the
acquired function even though it has not imported a schema that defines this
type.
At execution time, the schema available for validating instance documents contains (at least) the union of the schema components imported into all constituent packages of the stylesheet.
The xsl:global-context-item
element is used to declare whether a
global context item is required, and if so, what its
required type is.
The element is a declaration that
can appear at most once in any stylesheet module; and if more than one
xsl:global-context-item
declaration appears within a package, then the declarations must be consistent. Specifically, all
the attributes must have semantically-equivalent values.
Note:
This means that omitting an attribute is equivalent to specifying its default value explicitly; and purely lexical variations, such as the presence of whitespace in an attribute value, are not considered significant.
[ERR XTSE3087] It is a static error if more than
one xsl:global-context-item
declaration appears within a
stylesheet module, or if several modules within a
single package contain inconsistent
xsl:global-context-item
declarations
If there is no xsl:global-context-item
declaration for a package,
this is equivalent to specifying the empty element
<xsl:global-context-item/>
, which imposes no constraints.
<!-- Category: declaration -->
<xsl:global-context-item
as? = item-type
use? = "required" | "optional" | "absent" />
The use
attribute takes the value required
,
optional
, or absent
. The
default is optional
.
If the value required
is specified, then there must be a
global context item.
If the value optional
is specified, or if the attribute is
omitted, or if the xsl:global-context-item
element is
omitted, then there may or may not be a global context item.
If the value absent
is specified, then the global focus
(context item, position, and size) will be absent
Note:
This specification does not define whether supplying a global context item in this situation results in an error or warning, or whether the supplied context item is simply ignored.
If the as
attribute is present then its value must be an ItemTypeXP30. If the attribute is
omitted this is equivalent to specifying as="item()"
.
The as
attribute defines the required type of the global context
item. The default value is as="item()"
. If a global context item is
supplied then it must conform to the required type, after conversion (if
necessary) using the function conversion rules.
[ERR XTSE3089] It is a static error if the as
attribute is
present when use="absent"
is specified.
The global context item is available only within the top-level package. If a valid xsl:global-context-item
declaration appears within a library package, then it is
ignored, unless it specifies use="required"
, in which case an error
is signaled: [see ERR XTTE0590].
Note:
In earlier releases of this specification, the global context item and
the initial match selection were essentially the same thing, often referred
to as the principal source document. In XSLT 3.0, they have been separated:
the global context item is a single item accessible to the initializers of global
variables
as the value of the expression .
(dot), while the initial match selection
is a sequence of nodes or other items supplied to an initial implicit xsl:apply-templates
invocation.
APIs that were originally designed for use with earlier versions of XSLT are likely to bundle the two concepts together.
With a streamable processor, the initial match selection can consist of streamed nodes, but the global context item is always grounded, because it is available to all global variables and there is no control over the sequence of processing.
A type error is signaled if there
is a package with an xsl:global-context-item
declaration specifying a required type that does not match the supplied global context item. The error code is the same as for
xsl:param
: [see ERR XTTE0590].
Note:
If the ItemType
is one that can only be satisfied by a
schema-validated input document, for example
as="schema-element(invoice)"
, the processor may interpret this as a request to apply schema
validation to the input. Similarly, if the KindTest
indicates that
an element node is required, the processor may interpret this as a request to
supply the document element rather than the document node of a supplied input
document.
The example in this section illustrates the use of overrides to customize or
extend a (fictional) library package named
http://example.com/csv-parser
, which provides a parsing function
for data formatted as lines containing comma-separated values. For simplicity of
exposition, the example shows a simple, naive implementation; a realistic CSV
parser would be more complicated and make the example harder to follow.
The basic functionality of the package is provided by the function
csv:parse
, which expects a string parameter named
input
. By default, the function parses the input into lines,
and breaks lines on commas, returning as result an element named
csv
containing one row
element per line, each
row
containing a sequence of field
elements.
A simple stylesheet which uses this library and applies it to a string might
look like the following. The initial template applies csv:parse
to
a suitable string and returns a copy of the result:
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:csv="http://example.com/csv" exclude-result-prefixes="xs csv" version="3.0"> <xsl:output indent="yes"/> <xsl:use-package name="http://example.com/csv-parser" package-version="*"/> <!-- example input "file" --> <xsl:variable name="input" as="xs:string"> name,id,postal code "Abel Braaksma",34291,1210 KA "Anders Berglund",473892,9843 ZD </xsl:variable> <!-- entry point --> <xsl:template name="xsl:initial-template"> <xsl:copy-of select="csv:parse($input)"/> </xsl:template> </xsl:stylesheet>
The result returned by this stylesheet would be:
<csv> <row> <field quoted="no">name</field> <field quoted="no">id</field> <field quoted="no">postal code</field> </row> <row> <field quoted="yes">Abel Braaksma</field> <field quoted="no">34291</field> <field quoted="no">1210 KA</field> </row> <row> <field quoted="yes">Anders Berglund</field> <field quoted="no">473892</field> <field quoted="no">9843 ZD</field> </row> </csv>
Variations on this default behavior are achieved by overriding selected declarations in the package, as described below.
The package module itself is version 1.0.0 of a package called
http://example.com/csv-parser
; it has the following
structure:
<?xml version="1.0" encoding="UTF-8"?> <xsl:package name="http://example.com/csv-parser" package-version="1.0.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:csv="http://example.com/csv" exclude-result-prefixes="xs csv" declared-modes="yes" version="3.0"> <!--* Mode declarations ... *--> <!--* Variable declarations ... *--> <!--* Attribute-set declaration ... *--> <!--* Function declarations ... *--> <!--* Templates ... *--> </xsl:package>
The contents of the package (represented here by comments) are described more fully below.
csv:parse
Function and its User-customization HooksThe csv:parse
function is final and cannot be overridden. As can be
seen from the code below, it (1) parses its input
parameter into
lines, (2) calls function csv:preprocess-line
on each line, then
(3) applies the templates of mode csv:parse-line
to the
pre-processed value. The result is then (4) processed again by mode
csv:post-process
.
<xsl:function name="csv:parse" visibility="final"> <xsl:param name="input" as="xs:string"/> <xsl:variable name="result" as="element()"> <csv> <xsl:apply-templates select="(tokenize($input, $csv:line-separator) ! csv:preprocess-line(.))" mode="csv:parse-line"/> </csv> </xsl:variable> <xsl:apply-templates select="$result" mode="csv:post-process"/> </xsl:function>
The default code for this processing is given below. Each part of the processing except the first (the tokenization into lines) can be overridden by the user of the package.
The first user-customization hook is given by the global variable
csv:line-separator
, which specifies the line separator used to
break the input string into lines. It can be overridden by the user if need be.
The default declaration attempts to handle the line-separator sequences used by
most common operating systems in text files:
<xsl:variable name="csv:line-separator" as="xs:string" select="'\r\n?|\n\r?'" visibility="public"/>
The function csv:preprocess-line
calls
normalize-space()
on its argument:
<xsl:function name="csv:preprocess-line" as="xs:string?" visibility="public"> <xsl:param name="line" as="xs:string"/> <xsl:sequence select="normalize-space($line)"/> </xsl:function>
Because the function is declared public
, it can be overridden by a
user. (This might be necessary, for example, if whitespace within quoted
strings needs to be preserved.)
csv:parse-line
By default, the mode csv:parse-line
parses the current item (this
will be one line of the input data) into fields, using mode
csv:parse-field
on the individual fields and (by default)
wrapping the result in a row
element.
The mode is declared with visibility="public"
to allow it to be
called from elsewhere and overridden:
<xsl:mode name="csv:parse-line" visibility="public"/>
<xsl:template match="." mode="csv:parse-line"> <row> <xsl:apply-templates select="tokenize(., $csv:field-separator)" mode="csv:parse-field"/> </row> </xsl:template>
This relies on the variable csv:field-separator
, which is a comma
by default but which can be overridden by the user to parse tab-separated data
or data with other delimiters.
<xsl:variable name="csv:field-separator" as="xs:string" select="','" visibility="public"/>
The default implementation of csv:parse-line
does not handle
occurrences of the field separator occurring within quoted strings. The user
can add templates to the mode to provide that functionality.
csv:parse-field
Mode csv:parse-field
processes the current item as a field; by
default it strips quotation marks from the value, calls the function
csv:preprocess-field()
on it, and wraps the result in a
field
element, which carries the attributes declared in the
attribute set csv:field-attributes
.
<xsl:template match="." mode="csv:parse-field" expand-text="yes"> <xsl:variable name="string-body-pattern" as="xs:string" select="'([^' || $csv:validated-quote || ']*)'"/> <xsl:variable name="quoted-value" as="xs:string" select="$csv:validated-quote || $string-body-pattern || $csv:validated-quote"/> <xsl:variable name="unquoted-value" as="xs:string" select="'(.+)'"/> <field xsl:use-attribute-sets="csv:field-attributes">{ csv:preprocess-field( replace(., $quoted-value || '|' || $unquoted-value, '$1$2')) }</field> </xsl:template>
The attribute set csv:field-attributes
includes, by default, a
quoted
attribute which has the values yes
or
no
to show whether the input value was quoted or not.
<xsl:attribute-set name="csv:field-attributes" visibility="public"> <xsl:attribute name="quoted" select="if (starts-with(., $csv:validated-quote)) then 'yes' else 'no'"/> </xsl:attribute-set>
The mode csv:parse-field
is declared with
visibility="public"
to allow it to be called from elsewhere and
overridden; it specifies on-no-match="shallow-copy"
so that any
string not matching a template will simply be copied:
<xsl:mode name="csv:parse-field" on-no-match="shallow-copy" visibility="public"/>
csv:quote
VariableThe variable csv:quote
can be used to specify the character used
in a particular input stream to quote values.
<xsl:variable name="csv:quote" as="xs:string" select="'"'" visibility="public"/>
The template given above assumes that the variable is one character long. To
ensure that any overriding value of the variable is properly checked, references to
the value use a
second variable csv:validated-quote
, which
is declared private
to ensure that the checking cannot be
disabled.
<xsl:variable name="csv:validated-quote" visibility="private" as="xs:string" select=" if (string-length($csv:quote) ne 1) then error(xs:QName('csv:ERR001'), 'Incorrect length for $csv:quote, should be 1') else $csv:quote"/>
When the value of csv:quote
is not
exactly one character long, the reference to
csv:validated-quote
will cause an error (csv:ERR001)
to be raised.
csv:preprocess-field
FunctionThe function csv:preprocess-field
is called on each field after
any quotation marks are stripped and before it is written out as the value of a
field
element:
<xsl:function name="csv:preprocess-field" as="xs:string"> <xsl:param name="field" as="xs:string"/> <xsl:sequence select="$field"/> </xsl:function>
As can be seen, the function does nothing but return its input; its only purpose is to provide the opportunity for the user to supply a suitable function to be invoked at this point in the processing of each field.
csv:post-process
The mode csv:post-process
is intended solely as a hook for user
code. By default, it does nothing.
The package defines no templates for this mode; the mode definition makes it return a copy of its input:
<xsl:mode name="csv:post-process" on-no-match="shallow-copy" visibility="public"/>
As can be seen from the code shown above, the package provides several opportunities for users to override the default behavior:
The global variables csv:line-separator
,
csv:field-separator
, and csv:quote
can be
overridden to specify the character strings used to separate lines and
fields and to quote individual field values.
The function csv:preprocess-line
can be overridden to do
more (or less) than stripping white space; the function
csv:preprocess-field
can be overridden to process
individual field values.
Templates can be added to the modes csv:parse-line
,
csv:parse-field
, and csv:post-process
to
change their behavior.
The attribute set csv:field-attributes
can be overridden to
specify a different set of attributes (or none) for field
elements.
The following using stylesheet illustrates the use of the
xsl:override
element to take advantage of several of these
opportunities:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:csv="http://example.com/csv" exclude-result-prefixes="xs csv" version="3.0"> <xsl:output indent="yes"/> <xsl:use-package name="http://example.com/csv-parser" package-version="*"> <xsl:override> <!-- Change the root element from 'csv' to 'root' --> <xsl:template match="csv" mode="csv:post-process"> <root> <xsl:apply-templates mode="csv:post-process"/> </root> </xsl:template> <!-- add an extra attribute that uses the context item --> <xsl:attribute-set name="csv:field-attributes" use-attribute-sets="xsl:original"> <xsl:attribute name="type" select="if (. castable as xs:decimal) then 'numeric' else 'string'"/> </xsl:attribute-set> <!-- use semicolon not comma between fields --> <xsl:variable name="csv:field-separator" as="xs:string" select="';'" visibility="public"/> <!-- prevent empty rows from appearing with empty lines --> <xsl:function name="csv:preprocess-line" as="xs:string?" visibility="public"> <xsl:param name="line" as="xs:string"/> <xsl:variable name="norm-line" select="normalize-space(xsl:original($line))"/> <xsl:sequence select="if (string-length($norm-line) > 0) then $norm-line else ()"/> </xsl:function> </xsl:override> </xsl:use-package> <!-- example input "file" --> <xsl:variable name="input" as="xs:string"> name;id;postal code "Braaksma Abel";34291;1210 KA "Berglund Anders";473892;9843 ZD </xsl:variable> <!-- entry point --> <xsl:template name="xsl:initial-template"> <xsl:copy-of select="csv:parse($input)"/> </xsl:template> </xsl:stylesheet>
Note:
As it does elsewhere, the visibility of components declared within
xsl:override
defaults to private
; to keep
the component public, it is necessary to specify visibility
explicitly.
The types and optionality of all function parameters must match those of the function being overridden; for function overriding to be feasible, packages must document the function signature thoroughly.
The names, types, and optionality of all named-template parameters must match those of the template being overridden; for overriding to be feasible, packages must document the template signature thoroughly.
The values for the attributes in the attribute set
csv:field-attributes
are calculated once for each
element for which the attribute set is supplied; the
select
attributes which determine the values can thus
refer to the context item. Here, the value specification for the
type
attribute checks to see whether the string value
of the context item is numeric by inquiring whether it can be cast to
decimal, and sets the value for the type
attribute
accordingly.
The result returned by this stylesheet would be:
<root> <row> <field quoted="no" type="string">name</field> <field quoted="no" type="string">id</field> <field quoted="no" type="string">postal code</field> </row> <row> <field quoted="yes" type="string">Braaksma Abel</field> <field quoted="no" type="numeric">34291</field> <field quoted="no" type="string">1210 KA</field> </row> <row> <field quoted="yes" type="string">Berglund Anders</field> <field quoted="no" type="numeric">473892</field> <field quoted="no" type="string">9843 ZD</field> </row> </root>
[Definition: A package consists of one or more stylesheet modules, each one forming all or part of an XML document.]
Note:
A stylesheet module is represented by an XDM element node (see [XDM 3.0]). In the case of a standard stylesheet module, this
will be an xsl:stylesheet
or xsl:transform
element. In the case of a simplified stylesheet module, it can be any element (not
in the XSLT namespace) that has an
xsl:version
attribute.
Although stylesheet modules will commonly be maintained in the form of documents conforming to XML 1.0 or XML 1.1, this specification does not mandate such a representation. As with source trees, the way in which stylesheet modules are constructed, from textual XML or otherwise, is outside the scope of this specification.
The principal stylesheet module of a package may take one of three forms:
A package manifest, as described in 3.5 Packages, which is a
subtree rooted at an xsl:package
element
An implicit package, which is a subtree rooted at an
xsl:stylesheet
or xsl:transform
element.
This is transformed automatically to a package as described in 3.5 Packages.
A simplified stylesheet, which is a subtree rooted at a literal result element,
as described in 3.8 Simplified Stylesheet Modules. This is first converted
to an implicit package by wrapping it in an xsl:stylesheet
element using the transformation described in 3.8 Simplified Stylesheet Modules, and then to an explicit package (rooted at an
xsl:package
element) using the transformation described in
3.5 Packages.
A stylesheet module other than the principal stylesheet module of a package may take either of two forms:
[Definition: A
standard stylesheet module, which is a subtree rooted at an
xsl:stylesheet
or xsl:transform
element.]
[Definition: A simplified stylesheet, which is a subtree rooted at a literal result element, as described in 3.8 Simplified Stylesheet Modules. This is first converted to a standard stylesheet module by wrapping it in an xsl:stylesheet element using the transformation described in 3.8 Simplified Stylesheet Modules.]
Whichever of the above forms a module takes, the outermost
element (xsl:package
, xsl:stylesheet
, or a literal result element) may either be the outermost
element of an XML document, or it may be a child of some
(non-XSLT) element in a host document.
[Definition: A stylesheet module whose outermost element is the child of a non-XSLT element in a host document is referred to as an embedded stylesheet module. See 3.12 Embedded Stylesheet Modules.]
<xsl:stylesheet
id? = id
version = decimal
default-mode? = eqname | "#unnamed"
default-validation? = "preserve" | "strip"
input-type-annotations? = "preserve" | "strip" | "unspecified"
default-collation? = uris
extension-element-prefixes? = prefixes
exclude-result-prefixes? = prefixes
expand-text? = boolean
use-when? = expression
xpath-default-namespace? = uri >
<!-- Content: (declarations) -->
</xsl:stylesheet>
<xsl:transform
id? = id
version = decimal
default-mode? = eqname | "#unnamed"
default-validation? = "preserve" | "strip"
input-type-annotations? = "preserve" | "strip" | "unspecified"
default-collation? = uris
extension-element-prefixes? = prefixes
exclude-result-prefixes? = prefixes
expand-text? = boolean
use-when? = expression
xpath-default-namespace? = uri >
<!-- Content: (declarations) -->
</xsl:transform>
A stylesheet module is represented by an xsl:stylesheet
element in
an XML document. xsl:transform
is allowed as a synonym for
xsl:stylesheet
; everything this specification says about the
xsl:stylesheet
element applies equally to
xsl:transform
.
The version
attribute indicates the version
of XSLT that the stylesheet module requires. The attribute is
required.
[ERR XTSE0110] The value of the version
attribute must be a number:
specifically, it must be a valid instance of the type
xs:decimal
as defined in [XML Schema Part 2].
The version
attribute is intended to indicate the
version of the XSLT specification against which the stylesheet is written. In a
stylesheet written to use XSLT 3.0, the value should normally be
set to 3.0
. If the value is numerically less than 3.0
, the
stylesheet is processed using the rules for backwards compatible behavior
(see 3.9 Backwards Compatible Processing). If the value is numerically greater than
3.0
, the stylesheet is processed using the rules for forwards compatible behavior (see 3.10 Forwards Compatible Processing).
The effect of the input-type-annotations
attribute is described in
4.4.1 Stripping Type Annotations from a Source Tree.
The [xsl:]default-validation
attribute defines the default value of the
validation
attribute of all relevant instructions appearing within
its scope. For details of the effect of this attribute, see 25.4 Validation.
[ERR XTSE0120] An xsl:stylesheet
, xsl:transform
,
or xsl:package
element must not have any
text node children. (This rule applies after stripping of whitespace text nodes as described in 4.3 Stripping Whitespace from the Stylesheet.)
[Definition: An element occurring as a child of an
xsl:package
,
xsl:stylesheet
,
xsl:transform
, or xsl:override
element is called a top-level element.]
[Definition: Top-level elements fall into two categories: declarations, and user-defined data elements. Top-level elements whose names are in the XSLT namespace are declarations. Top-level elements in any other namespace are user-defined data elements (see 3.7.3 User-defined Data Elements)].
The declaration elements permitted in the
xsl:stylesheet
element are:
xsl:accumulator
xsl:attribute-set
xsl:character-map
xsl:decimal-format
xsl:function
xsl:global-context-item
xsl:import
xsl:import-schema
xsl:include
xsl:key
xsl:mode
xsl:namespace-alias
xsl:output
xsl:param
xsl:preserve-space
xsl:strip-space
xsl:template
xsl:use-package
xsl:variable
Note that the xsl:variable
and xsl:param
elements
can act either as declarations or as instructions. A global variable or parameter is
defined using a declaration; a local variable or parameter using an instruction.
The child elements of the xsl:stylesheet
element may appear in any order. In most cases, the ordering of these elements does
not affect the results of the transformation; however:
As described in 6.4 Conflict Resolution for Template Rules, when two template rules with the same priority match the same nodes, there are situations where the order of the template rules will affect which is chosen.
Forwards references to static variables are not allowed in static expressions.
default-collation
AttributeThe default-collation
attribute is a standard attribute that may appear on
any element in the XSLT namespace, or (as xsl:default-collation
) on a
literal result element.
The attribute, when it appears on an element
E, is used to specify the default collation used by all XPath
expressions appearing in attributes or text value templates that have E as an
ancestor, unless overridden by another default-collation
attribute on an inner element. It also determines the collation used by certain
XSLT constructs (such as xsl:key
and
xsl:for-each-group
) within its scope.
The value of the attribute is a whitespace-separated list of collation URIs. If any of these URIs is a relative URI reference, then it is resolved relative to the base URI of the attribute’s parent element. If the implementation recognizes one or more of the resulting absolute collation URIs, then it uses the first one that it recognizes as the default collation.
[ERR XTSE0125] It is a static error if the value
of an [xsl:]default-collation
attribute, after resolving
against the base URI, contains no URI that the implementation recognizes as
a collation URI.
Note:
The reason the attribute allows a list of collation URIs is that collation URIs
will often be meaningful only to one particular XSLT implementation.
Stylesheets designed to run with several different implementations can
therefore specify several different collation URIs, one for use with each. To
avoid the above error condition, it is possible to include as the last
collation URI in the list either the Unicode Codepoint Collation or a collation in the UCA family (see 13.4 The Unicode Collation Algorithm) with the parameter
fallback=yes
.
The [xsl:]default-collation
attribute does not affect the collation
used by xsl:sort
or by xsl:merge
.
In the absence of an
[xsl:]default-collation
attribute, the default collation
may be set by the calling application in an implementation-defined way. The recommended default, unless the user
chooses otherwise, is to use the Unicode codepoint collation.
default-mode
AttributeThe [xsl:]default-mode
attribute defines the default value for the
mode attribute of all
xsl:template
and xsl:apply-templates
elements
within its scope.
More specifically, when an element E matches
the pattern (xsl:template[@match] | xsl:apply-templates)[not(@mode) or
normalize-space(@mode) eq "#default"]
(using the Unicode codepoint
collation), then the effective value of the mode
attribute is taken
from the value of the [xsl:]default-mode
attribute of the innermost
ancestor-or-self element of E that has such an attribute. If there is
no such element, then the default is the unnamed
mode. This is equivalent to specifying #unnamed
.
In addition, when the attribute appears on the xsl:package
,
xsl:stylesheet
, or xsl:transform
element of the
principal stylesheet module of the top-level package,
it provides a default value for the initial mode used on stylesheet
invocation.
The value of the [xsl:]default-mode
attribute must
either be an EQName, or the token #unnamed
which refers to
the unnamed mode.
Note:
This attribute is provided to support an approach to stylesheet modularity in which all the template rules for one mode are collected together into a single stylesheet module. Using this attribute reduces the risk of forgetting to specify the mode in one or more places where it is needed, and it also makes it easier to reuse an existing stylesheet module that does not use modes in an application where modes are needed to avoid conflicts with existing template rules.
It is not necessary for the referenced mode to be
explicitly declared in an xsl:mode
declaration, unless this is
mandated by the declared-modes
attribute (which defaults to
yes
on an xsl:package
element).
[Definition: In addition to
declarations, the
xsl:stylesheet
element may contain among its children any
element not from the XSLT namespace,
provided that the expanded QName of
the element has a non-null namespace URI. Such elements are referred to as
user-defined data elements.]
[ERR XTSE0130] It is a static error if an
xsl:stylesheet
, xsl:transform
,
or xsl:package
element has a child element whose name
has a null namespace URI.
An implementation may attach an implementation-defined meaning to user-defined data elements that
appear in particular namespaces. The set of namespaces that are recognized for
such data elements is implementation-defined. The presence of a user-defined data element
must not change the behavior of XSLT elements and functions defined in this
document; for example, it is not permitted for a user-defined data element to
specify that xsl:apply-templates
should use different rules to
resolve conflicts. The constraints on what user-defined data elements can and
cannot do are exactly the same as the constraints on extension attributes, described in
3.2 Extension Attributes. Thus, an implementation is always free
to ignore user-defined data elements, and must ignore such data
elements without giving an error if it does not recognize the namespace URI.
User-defined data elements can provide, for example,
information used by extension instructions or extension functions (see 24 Extensibility and Fallback),
information about what to do with any final result tree,
information about how to construct source trees,
optimization hints for the processor,
metadata about the stylesheet,
structured documentation for the stylesheet.
A simplified syntax is allowed for a stylesheet
module that defines only a single template rule for the document node.
The stylesheet module may consist of just a literal result element (see 11.1 Literal Result Elements)
together with its contents. The literal result element must have an
xsl:version
attribute (and it must therefore also declare the XSLT
namespace). Such a stylesheet module is equivalent to a standard stylesheet module
whose xsl:stylesheet
element contains a template rule containing the literal result
element, minus its xsl:version
attribute; the template rule has a match
pattern of /
.
For example:
<html xsl:version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Expense Report Summary</title> </head> <body> <p>Total Amount: <xsl:value-of select="expense-report/total"/></p> </body> </html>
has the same meaning as
<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml"> <xsl:template match="/"> <html> <head> <title>Expense Report Summary</title> </head> <body> <p>Total Amount: <xsl:value-of select="expense-report/total"/></p> </body> </html> </xsl:template> </xsl:stylesheet>
Note that it is not possible, using a simplified stylesheet, to request that the
serialized output contains a DOCTYPE
declaration. This can only be
done by using a standard stylesheet module, and using the
xsl:output
element.
More formally, a simplified stylesheet module is equivalent to the standard
stylesheet module that would be generated by applying the following transformation
to
the simplified stylesheet module, invoking the transformation by calling the named template
expand
, with the containing literal result element as the context node:
<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template name="expand"> <xsl:element name="xsl:stylesheet"> <xsl:attribute name="version" select="@xsl:version"/> <xsl:element name="xsl:template"> <xsl:attribute name="match" select="'/'"/> <xsl:copy-of select="."/> </xsl:element> </xsl:element> </xsl:template> </xsl:stylesheet>
[ERR XTSE0150] A literal result element
that is used as the outermost element of a simplified stylesheet module
must have an xsl:version
attribute. This indicates the version of XSLT that the stylesheet requires. For this
version of XSLT, the value will normally be
3.0
; the value must be a valid instance of the type
xs:decimal
as defined in [XML Schema Part 2].
The allowed content of a literal result element when used as a simplified stylesheet
is the same as when it occurs within a sequence constructor. Thus, a literal result element used as the
document element of a simplified stylesheet cannot contain declarations. Simplified stylesheets therefore
cannot use template rules, global variables, stylesheet parameters, stylesheet functions, keys, attribute-sets, or
output definitions. In turn this
means that the only useful way to initiate the transformation is to supply a document
node as the initial match selection, to be matched by the implicit
match="/"
template rule using the unnamed mode.
[Definition: The effective
version of an element in a stylesheet module or package manifest is the decimal value of the [xsl:]version
attribute
(see 3.4 Standard Attributes) on that element or on the innermost
ancestor element that has such an attribute, excluding the version
attribute on an xsl:output
element.]
[Definition: An element is processed with backwards compatible behavior if its
effective version is less than
3.0
.]
Specifically:
If the effective version is equal to 1.0, then the element is processed with XSLT 1.0 behavior as described in 3.9.1 XSLT 1.0 Compatibility Mode.
If the effective version is equal to 2.0, then the element is processed with XSLT 2.0 behavior as described in 3.9.2 XSLT 2.0 Compatibility Mode.
If the effective version is any other value less than 3.0, the recommended action is to report a static error; however, processors may recognize such values and process the element in an implementation-defined way.
Note:
XSLT 1.0 allowed the version
attribute to take any decimal
value, and invoked forwards compatible processing for any value other than
1.0. XSLT 2.0 allowed the attribute to take any decimal value, and invoked
backwards compatible (i.e. 1.0-compatible) processing for any value less
than 2.0. Some stylesheets may therefore be encountered that use values
other than 1.0 or 2.0. In particular, the value 1.1 is sometimes
encountered, as it was used at one stage in a draft language proposal.
These rules do not apply to the xsl:output
element, whose
version
attribute has an entirely different purpose: it is used to
define the version of the output method to be used for serialization.
It is implementation-defined whether a particular XSLT 3.0 implementation supports backwards compatible behavior for any XSLT version earlier than XSLT 3.0.
[ERR XTDE0160] It is a dynamic error if an element has an effective version of V (with V < 3.0) when the implementation does not support backwards compatible behavior for XSLT version V.
Note:
By making use of backwards compatible behavior, it is possible to write the stylesheet in a way that ensures that its results when processed with an XSLT 3.0 processor are identical to the effects of processing the same stylesheet using a processor for an earlier version of XSLT. To assist with transition, some parts of a stylesheet may be processed with backwards compatible behavior enabled, and other parts with this behavior disabled.
All data values manipulated by an XSLT 3.0 processor are defined by the XDM data model, whether or not the relevant expressions use backwards compatible behavior. Because the same data model is used in both cases, expressions are fully composable. The result of evaluating instructions or expressions with backwards compatible behavior is fully defined in the XSLT 3.0 and XPath 3.0 specifications, it is not defined by reference to earlier versions of the XSLT and XPath specifications.
To write a stylesheet that makes use of features that
are new in version N, while also working with a processor that only
supports XSLT version M (M < N),
it is necessary to understand both the rules for backwards compatible behavior in
XSLT version N, and the rules for
forwards compatible behavior in XSLT version
M. If the xsl:stylesheet
element
specifies version="2.0"
or version="3.0"
, then an XSLT 1.0
processor will ignore XSLT 2.0 and XSLT 3.0
declarations that were not defined in XSLT
1.0, for example xsl:function
and
xsl:import-schema
. If any new XSLT
3.0 instructions are used (for example xsl:evaluate
or xsl:source-document
), or if new XPath
3.0 features are used (for example, new functions, or let expressions), then the stylesheet must provide
fallback behavior that relies only on facilities available in the earliest XSLT version supported. The fallback
behavior can be invoked by using the xsl:fallback
instruction, or
by testing the results of the function-available
or
element-available
functions, or by testing the value of
the xsl:version
property returned by the
system-property
function.
[Definition: An element in the stylesheet is processed with XSLT 1.0 behavior if its effective version is equal to 1.0.]
In this mode, if any attribute contains an XPath expression, then the expression is evaluated with XPath 1.0 compatibility mode set to
true
. For details of this mode, see Section
2.1.1 Static Context
XP30. Expressions contained in
text value templates are
always evaluated with XPath 1.0
compatibility mode set to false
, since this construct
was not available in XSLT 1.0.
Furthermore, in such an expression any function call for which no implementation is available (unless it uses the standard function namespace) is bound to a fallback error function whose effect when evaluated is to raise a dynamic error [see ERR XTDE1425] . The effect is that with backwards compatible behavior enabled, calls on extension functions that are not available in a particular implementation do not cause an error unless the function call is actually evaluated. For further details, see 24.1 Extension Functions.
Note:
This might appear to contradict the specification of XPath 3.0, which states that a static error [XPST0017] is raised when an expression contains a call to a function that is not present (with matching name and arity) in the static context. This apparent contradiction is resolved by specifying that the XSLT processor constructs a static context for the expression in which every possible function name and arity (other than names in the standard function namespace) is present; when no other implementation of the function is available, the function call is bound to a fallback error function whose run-time effect is to raise a dynamic error.
Certain XSLT constructs also produce different results when XSLT 1.0 compatibility mode is enabled. This is described separately for each such construct.
Processing an instruction with XSLT 1.0 behavior is not compatible with streaming. More specifically, and notwithstanding anything stated in 19 Streamability, an instruction that is processed with XSLT 1.0 behavior is roaming and free-ranging, which has the effect that any construct containing such an instruction is not guaranteed-streamable.
[Definition: An element is processed with XSLT 2.0 behavior if its effective version is equal to 2.0.]
In this specification, no differences are defined for XSLT 2.0 behavior. An XSLT 3.0 processor will therefore produce the same results whether the effective version of an element is set to 2.0 or 3.0.
Note:
An XSLT 2.0 processor, by contrast, will in some cases produce different
results in the two cases. For example, if the stylesheet contains an
xsl:iterate
instruction with an
xsl:fallback
child, an XSLT 3.0 processor will process the
xsl:iterate
instruction regardless whether the effective
version is 2.0 or 3.0, while an XSLT 2.0 processor will report a static error
if the effective version is 2.0, and will take the fallback action if the
effective version is 3.0.
The intent of forwards compatible behavior is to make it possible to write a stylesheet that takes advantage of features introduced in some version of XSLT subsequent to XSLT 3.0, while retaining the ability to execute the stylesheet with an XSLT 3.0 processor using appropriate fallback behavior.
It is always possible to write conditional code to run under different XSLT versions
by using the use-when
feature described in 3.13.1 Conditional Element Inclusion. The rules for forwards compatible behavior
supplement this mechanism in two ways:
certain constructs in the stylesheet that mean nothing to an XSLT 3.0 processor are ignored, rather than being treated as errors.
explicit fallback behavior can be defined for instructions defined in a future
XSLT release, using the xsl:fallback
instruction.
The detailed rules follow.
[Definition: An
element is processed with forwards compatible behavior if its
effective version is greater than
3.0
.]
These rules do not apply to the version
attribute of the
xsl:output
element, which has an entirely different purpose: it
is used to define the version of the output method to be used for serialization.
When an element is processed with forwards compatible behavior:
If the element is in the XSLT namespace and appears as a child of the
xsl:stylesheet
element, and XSLT 3.0 does not allow the element to appear as a child of the
xsl:stylesheet
element, then the element and its content
must be ignored.
If the element has an attribute that XSLT 3.0 does not allow the element to have, then the attribute must be ignored.
If the element is in the XSLT namespace and appears as a child of an element whose content model requires a sequence constructor, and XSLT 3.0 does not allow such elements to appear as part of a sequence constructor, then:
If the element has one or more xsl:fallback
children,
then no error is reported either statically or dynamically, and the
result of evaluating the instruction is the concatenation of the
sequences formed by evaluating the sequence constructors within its
xsl:fallback
children, in document order. Siblings of
the xsl:fallback
elements are ignored, even if they are
valid XSLT 3.0 instructions.
If the element has no xsl:fallback
children, then a
static error is reported in the same way as if forwards compatible
behavior were not enabled.
For example, an XSLT 3.0 processor will process the following stylesheet without error, although the stylesheet includes elements from the XSLT namespace that are not defined in this specification:
<xsl:stylesheet version="17.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/"> <xsl:exciting-new-17.0-feature> <xsl:fly-to-the-moon/> <xsl:fallback> <html> <head> <title>XSLT 17.0 required</title> </head> <body> <p>Sorry, this stylesheet requires XSLT 17.0.</p> </body> </html> </xsl:fallback> </xsl:exciting-new-17.0-feature> </xsl:template> </xsl:stylesheet>
Note:
If a stylesheet depends crucially on a declaration introduced by a version of XSLT after 3.0, then the stylesheet can use an
xsl:message
element with terminate="yes"
(see
23.1 Messages) to ensure that implementations that conform to an
earlier version of XSLT will not silently ignore the declaration.
For example,
<xsl:stylesheet version="18.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:important-new-17.0-declaration/> <xsl:template match="/"> <xsl:choose> <xsl:when test="number(system-property('xsl:version')) lt 17.0"> <xsl:message terminate="yes"> <xsl:text>Sorry, this stylesheet requires XSLT 17.0.</xsl:text> </xsl:message> </xsl:when> <xsl:otherwise> ... </xsl:otherwise> </xsl:choose> </xsl:template> ... </xsl:stylesheet>
Note:
The XSLT 1.0 and XSLT 2.0 specifications did not anticipate the
introduction of the xsl:package
element. An XSLT 1.0 or 2.0
processor encountering this element will report a static error, regardless of the
version
setting.
This problem can be circumvented by using the simplified package
syntax (whereby an
xsl:stylesheet
element is implicitly treated as
xsl:package
), or by writing the stylesheet code in
a separate module from the package manifest, and using the separate module as the
version of the stylesheet that is presented to a 2.0 processor.
XSLT provides two mechanisms to construct a package from multiple stylesheet modules:
an inclusion mechanism that allows stylesheet modules to be combined without changing the semantics of the modules being combined, and
an import mechanism that allows stylesheet modules to override each other.
The include and import mechanisms use two declarations,
xsl:include
and xsl:import
, which are defined
in the sections that follow.
These declarations use an href
attribute, whose value is a URI reference, to identify the stylesheet module to be included or
imported. If the value of this attribute is a relative URI reference, it is resolved as described in 5.8 URI References.
After resolving against the base URI, the way in which the URI reference is used to locate a representation of a stylesheet module, and the way in which the stylesheet module is constructed from that representation, are implementation-defined. In particular, it is implementation-defined which URI schemes are supported, whether fragment identifiers are supported, and what media types are supported. Conventionally, the URI is a reference to a resource containing the stylesheet module as a source XML document, or it may include a fragment identifier that selects an embedded stylesheet module within a source XML document; but the implementation is free to use other mechanisms to locate the stylesheet module identified by the URI reference.
The referenced stylesheet module must be either a standard stylesheet module or a simplified stylesheet. It must not be a package manifest. If it is a simplified stylesheet module then it is transformed into the equivalent standard stylesheet module by applying the transformation described in 3.8 Simplified Stylesheet Modules.
Implementations may choose to accept URI references containing a fragment identifier defined by reference to the XPointer specification (see [XPointer Framework]). Note that if the implementation does not support the use of fragment identifiers in the URI reference, then it will not be possible to include an embedded stylesheet module.
[ERR XTSE0165] It is a static error if the processor is not able to retrieve the resource identified by the URI reference, or if the resource that is retrieved does not contain a stylesheet module.
Note:
It is appropriate to use this error code when the resource cannot be retrieved, or when the retrieved resource is not well formed XML. If the resource contains XML that can be parsed but that violates the rules for stylesheet modules, then a more specific error code may be more appropriate.
<!-- Category: declaration -->
<xsl:include
href = uri />
A stylesheet module may include another stylesheet module using an
xsl:include
declaration.
The xsl:include
declaration has a required
href
attribute whose value is a URI reference identifying the
stylesheet module to be included. This attribute is used as described in 3.11.1 Locating Stylesheet Modules.
[ERR XTSE0170] An xsl:include
element must be a
top-level element.
[Definition: A stylesheet
level is a collection of stylesheet modules connected using xsl:include
declarations: specifically, two stylesheet modules A and
B are part of the same stylesheet level if one of them includes
the other by means of an xsl:include
declaration, or if there
is a third stylesheet module C that is in the same stylesheet level
as both A and B.]
Note:
A stylesheet level thus groups the declarations in a package by import precedence: two declarations within a package are in the same stylesheet level if and only if they have the same import precedence.
[Definition: The declarations within a stylesheet level have a total ordering
known as declaration order. The order of declarations within a
stylesheet level is the same as the document order that would result if each
stylesheet module were inserted textually in place of the
xsl:include
element that references it.] In other
respects, however, the effect of xsl:include
is not equivalent to
the effect that would be obtained by textual inclusion.
[ERR XTSE0180] It is a static error if a stylesheet module directly or indirectly includes itself.
Note:
It is not intrinsically an error for a stylesheet to include the same module more than once. However, doing so can cause errors because of duplicate definitions. Such multiple inclusions are less obvious when they are indirect. For example, if stylesheet B includes stylesheet A, stylesheet C includes stylesheet A, and stylesheet D includes both stylesheet B and stylesheet C, then A will be included indirectly by D twice. If all of B, C and D are used as independent stylesheets, then the error can be avoided by separating everything in B other than the inclusion of A into a separate stylesheet B′ and changing B to contain just inclusions of B′ and A, similarly for C, and then changing D to include A, B′, C′.
<!-- Category: declaration -->
<xsl:import
href = uri />
A stylesheet module may import another stylesheet module using an xsl:import
declaration. Importing a stylesheet module
is the same as including it (see 3.11.2 Stylesheet Inclusion) except that template rules and other declarations in the importing module take
precedence over template rules and declarations in the imported module; this is
described in more detail below.
The xsl:import
declaration has a required
href
attribute whose value is a URI reference identifying the
stylesheet module to be included. This attribute is used as described in 3.11.1 Locating Stylesheet Modules.
[ERR XTSE0190] An xsl:import
element must be a top-level element.
xsl:import
For example,
<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:import href="article.xsl"/> <xsl:import href="bigfont.xsl"/> <xsl:attribute-set name="note-style"> <xsl:attribute name="font-style">italic</xsl:attribute> </xsl:attribute-set> </xsl:stylesheet>
[Definition: The stylesheet levels making up a stylesheet are treated as forming an
import tree. In the import tree, each stylesheet level has one
child for each xsl:import
declaration that it
contains.] The ordering of the children is the declaration order of the
xsl:import
declarations within their stylesheet level.
[Definition: A declaration D in the stylesheet is defined to have lower import precedence than another declaration E if the stylesheet level containing D would be visited before the stylesheet level containing E in a post-order traversal of the import tree (that is, a traversal of the import tree in which a stylesheet level is visited after its children). Two declarations within the same stylesheet level have the same import precedence.]
For example, suppose
stylesheet module A imports stylesheet modules B and C in that order;
stylesheet module B imports stylesheet module D;
stylesheet module C imports stylesheet module E.
Then the import tree has the following structure:
The order of import precedence (lowest first) is D, B, E, C, A.
In general, a declaration with higher import precedence takes precedence over a declaration with lower import precedence. This is defined in detail for each kind of declaration.
[ERR XTSE0210] It is a static error if a stylesheet module directly or indirectly imports itself.
Note:
The case where a stylesheet module with a particular URI is imported several times is not treated specially. The effect is exactly the same as if several stylesheet modules with different URIs but identical content were imported. This might or might not cause an error, depending on the content of the stylesheet module.
An embedded stylesheet module is a stylesheet module whose containing element is not the outermost element of the containing XML document. Both standard stylesheet modules and simplified stylesheet modules may be embedded in this way.
Two situations where embedded stylesheets may be useful are:
The stylesheet may be embedded in the source document to be transformed.
The stylesheet may be embedded in an XML document that describes a sequence of processing of which the XSLT transformation forms just one part.
The xsl:stylesheet
element may have an
id
attribute to facilitate reference to the stylesheet module within
the containing document.
Note:
In order for such an attribute value to be used as a fragment identifier in a URI,
the XDM attribute node must generally have the is-id
property: see
Section
5.5 is-id Accessor
DM30. This property will typically be set if
the attribute is defined in a DTD as being of type ID
, or if it is
defined in a schema as being of type xs:ID
. It is also necessary that
the media type of the containing document should support the use of ID values as
fragment identifiers.
Such support is widespread in existing products, and is
endorsed in respect of the media type application/xml
by [RFC7303].
An alternative, if the implementation supports it, is to use an
xml:id
attribute. XSLT allows this attribute (like other
namespaced attributes) to appear on any XSLT
element.
The following example shows how the xml-stylesheet
processing
instruction (see [XML Stylesheet]) can be used to allow a source
document to contain its own stylesheet. The URI reference uses a fragment identifier
to locate the
xsl:stylesheet
element:
<?xml-stylesheet type="application/xslt+xml" href="#style1"?> <!DOCTYPE doc SYSTEM "doc.dtd"> <doc> <head> <xsl:stylesheet id="style1" version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format"> <xsl:import href="doc.xsl"/> <xsl:template match="id('foo')"> <fo:block font-weight="bold"><xsl:apply-templates/></fo:block> </xsl:template> <xsl:template match="xsl:stylesheet"> <!-- ignore --> </xsl:template> </xsl:stylesheet> </head> <body> <para id="foo"> ... </para> </body> </doc>
Note:
A stylesheet module that is embedded in the document to which it is to be applied
typically needs to contain a template
rule that specifies that xsl:stylesheet
elements are
to be ignored.
Note:
The above example uses the pseudo-attribute
type="application/xslt+xml"
in the xml-stylesheet
processing instruction to denote an XSLT stylesheet. This is the officially
registered media type for XSLT: see 3.3 XSLT Media Type. However,
browsers developed before this media type was registered are more likely to accept
the unofficial designation type="text/xsl"
.
Note:
Support for the xml-stylesheet
processing instruction is not required
for conformance with this Recommendation. Implementations are not constrained in
the mechanisms they use to identify a stylesheet when a transformation is
initiated: see 2.3 Initiating a Transformation.
This specification provides two features that cause the
raw stylesheet to be preprocessed as the first stage of static processing: elements
may be conditionally included or excluded by means of an [xsl:]use-when
attribute as described in 3.13.1 Conditional Element Inclusion, and attributes may
be conditionally computed as described in 3.13.2 Shadow Attributes.
Note that many of the rules affecting the validity of stylesheet documents apply to a stylesheet after this preprocessing phase has been carried out.
Any element in the XSLT namespace may have a use-when
attribute whose
value is an XPath expression that can be evaluated statically.
A literal result element, or
any other element within a stylesheet
module that is not in the XSLT namespace, may similarly carry an
xsl:use-when
attribute.
If the attribute is
present and the effective boolean
valueXP30 of the expression is false, then the element, together with
all the nodes having that element as an ancestor, is effectively excluded from the
stylesheet module. When a node is
effectively excluded from a stylesheet module the stylesheet module has the same
effect as if the node were not there. Among other things this means that no static
or dynamic errors will be reported in respect of the element and its contents,
other than errors in the use-when
attribute itself.
Note:
This does not apply to XML parsing or validation errors, which will be reported
in the usual way. It also does not apply to attributes that are necessarily
processed before [xsl:]use-when
, examples being
xml:space
and [xsl:]xpath-default-namespace
.
If the xsl:package
,
xsl:stylesheet
or xsl:transform
element
itself is effectively excluded, the effect is to exclude all the children of the
xsl:stylesheet
or xsl:transform
element, but
not the xsl:stylesheet
or xsl:transform
element
or its attributes.
Note:
This allows all the declarations that depend on the same condition to be
included in one stylesheet module, and for their inclusion or exclusion to be
controlled by a single use-when
attribute at the level of the
module.
Conditional element exclusion happens after stripping of whitespace text nodes from the stylesheet, as described in 4.3 Stripping Whitespace from the Stylesheet.
The XPath expression used as the value of the
xsl:use-when
attribute follows the rules for static expressions, including the rules for handling errors.
The use of [xsl:]use-when
is illustrated in the following
examples.
This example demonstrates the use of the use-when
attribute to
achieve portability of a stylesheet across schema-aware and non-schema-aware
processors.
<xsl:import-schema schema-location="http://example.com/schema" use-when="system-property('xsl:is-schema-aware')='yes'"/> <xsl:template match="/" use-when="system-property('xsl:is-schema-aware')='yes'" priority="2"> <xsl:result-document validation="strict"> <xsl:apply-templates/> </xsl:result-document> </xsl:template> <xsl:template match="/"> <xsl:apply-templates/> </xsl:template>
The effect of these declarations is that a non-schema-aware processor ignores
the xsl:import-schema
declaration and the first template rule,
and therefore generates no errors in respect of the schema-related constructs
in these declarations.
This example includes different stylesheet modules depending on which XSLT processor is in use.
<xsl:include href="module-A.xsl" use-when="system-property('xsl:vendor')='vendor-A'"/> <xsl:include href="module-B.xsl" use-when="system-property('xsl:vendor')='vendor-B'"/>
When a no-namespace attribute name N is permitted to appear on an element in the XSLT namespace (provided that N does not start with an underscore), then a value V can be supplied for N in one of two ways:
The conventional way is for an attribute node with name N and value V to appear in the XDM representation of the element node in the stylesheet tree.
As an alternative, a shadow attribute may be supplied allowing the value V to be statically computed during the preprocessing phase. The shadow attribute has a name that is the same as the name N prefixed with an underscore, and the value of the shadow attribute is a value template in which all expressions enclosed between curly braces must be static expressions. The value V is the result of evaluating the value template. If a shadow attribute is present, then any attribute node with name N (sharing the same parent element) is ignored.
For example, an xsl:include
element might be written:
<xsl:include _href="common{$VERSION}.xsl"/>
allowing the stylesheet to include a specific version of a library module based on the value of a static parameter.
Similarly, a mode might be declared like this:
<xsl:param name="streamable" as="xs:boolean" required="yes" static="yes"/> <xsl:mode _streamable="{$streamable}" on-no-match="shallow-skip"/>
this allowing the streamability of the mode to be controlled using a static parameter
(Note: this example relies on the fact that the
streamable
attribute accepts a boolean value, which means that
the values true
and false
are accepted as synonyms of
yes
and no
).
This mechanism applies to all attributes in the stylesheet where the attribute
name is in no namespace and the name of the parent element is in the XSLT namespace. This includes attributes that have static
significance such as the use-when
attribute, the version
attribute, and the static
attribute on xsl:variable
.
The mechanism does not apply to shadow attributes (that is, it is not possible to
invoke two stages of preprocessing by using two leading underscores). It does not
apply to attributes of literal result elements, nor to attributes in a namespace
such as the XML or XSLT namespace, nor to namespace declarations.
Note:
If a shadow attribute and its corresponding target attribute are both present in the stylesheet, the non-shadow attribute is ignored. This may be useful to make stylesheet code compatible across XSLT versions; an XSLT 2.0 processor operating in forwards compatible mode will ignore shadow attributes, and will require the target attribute to be valid.
Note:
The statement that the non-shadow attribute is ignored extends to error detection: it is not an error if the non-shadow attribute has an invalid value. However, this is not reflected in the schema for XSLT stylesheets, so validation using this schema may report errors in such cases.
Note:
An attribute whose name begins with an underscore is treated specially only when it appears on an element in the XSLT namespace. On a literal result element, it is treated in the same way as any other attribute (that is, its effective value is copied to the result tree). On an extension instruction or user-defined data element, as with other attributes on these elements, its meaning is entirely implementation-defined.
Although it is not usually considered good practice, it sometimes happens that variants or versions of an XML vocabulary exist in which the same local names are used, but in different namespaces. There is then a requirement to write code that will process source documents in a variety of different namespaces.
It is possible to define a static stylesheet parameter containing the target namespace, for example:
<xsl:param name="NS" as="xs:string" static="yes" select="'http://example.com/ns/one'"/>
And this can then be used to set the default namespace for XPath expressions:
_xpath-default-namespace="{$NS}"
However, it is not possible to put this shadow attribute on the
xsl:stylesheet
or xsl:package
element of
the principal stylesheet module, because at that point the variable
$NS
is not in scope. A workaround is to create a stub
stylesheet module which contains nothing but the static parameter declaration
and an xsl:include
of the stylesheet module containing the
real logic. The static stylesheet parameter will then be in scope on the
xsl:stylesheet
element of the included stylesheet module,
and the shadow attribute _xpath-default-namespace="{$NS}"
can
therefore appear on this xsl:stylesheet
element.
The following stylesheet produces a report giving information about selected employees. The predicate defining which employees are to be included in the report is supplied (as a string containing an XPath expression) in a static stylesheet parameter:
<xsl:param name="filter" static="yes" as="xs:string" select="'true()'"/> <xsl:function name="local:filter" as="xs:boolean"> <xsl:param name="e" as="element(employee)"/> <xsl:sequence _select="$e/({$filter})"/> </xsl:function> <xsl:template match="/"> <report> <xsl:apply-templates mode="report" select="//employee[local:filter(.)]"/> </report> </xsl:template>
If the supplied value of the filter parameter is, say location =
"UK"
, then the report will cover employees based in the UK.
Note:
The stylesheet function local:filter
is used here in preference
to direct use of the supplied predicate within the select
attribute of the xsl:apply-templates
instruction because it
reduces exposure to code injection attacks. It does not necessarily
eliminate all such risks, however. For example, it would be possible for a
caller to supply an expression that never terminates, thus creating a
denial-of-service risk.
Every XSLT 3.0 processor includes the following named type definitions in the in-scope schema components:
All built-in types defined in [XML Schema Part 2], including xs:anyType
and
xs:anySimpleType
.
The following types defined in [XPath 3.0]:
xs:yearMonthDuration
, xs:dayTimeDuration
,
xs:anyAtomicType
, xs:untyped
, and
xs:untypedAtomic
.
XSLT 3.0 processors may optionally include types
defined in XSD 1.1 (see [XML Schema 1.1 Part 1]). XSD 1.1 adopts the types
xs:yearMonthDuration
, xs:dayTimeDuration
, and
xs:anyAtomicType
previously defined in XPath 2.0, and adds one new
type: xs:dateTimeStamp
. XSD 1.1 also allows implementers to define
additional primitive types, and XSLT 3.0 permits such types to be supported by an
XSLT processor.
A schema-aware XSLT processor additionally supports:
User-defined types, and element and attribute declarations, that are imported
using an xsl:import-schema
declaration as described in
3.15 Importing Schema Components. These may include both simple and complex
types.
Note:
The names that are imported from the XML Schema namespace do not include all the
names of top-level types defined in either the Schema for Schema Documents or the
Schema for Schema Documents (Datatypes). The Schema for Schema Documents, as well
as defining built-in types such as xs:integer
and
xs:double
, also defines types that are intended for use only
within that schema, such as xs:derivationControl
. A stylesheet that is designed to process XML Schema
documents as its input or output may import the Schema for Schema Documents.
An implementation may define mechanisms that allow additional schema components to be added to the in-scope schema components for the stylesheet. For example, the mechanisms used to define extension functions (see 24.1 Extension Functions) may also be used to import the types used in the interface to such functions.
These schema components are the only
ones that may be referenced in XPath expressions within the stylesheet, or in the
[xsl:]type
and as
attributes of those elements that
permit these attributes.
Note:
The facilities described in this section are not available with a basic XSLT processor. They require a schema-aware XSLT processor, as described in 27 Conformance.
<!-- Category: declaration -->
<xsl:import-schema
namespace? = uri
schema-location? = uri >
<!-- Content: xs:schema? -->
</xsl:import-schema>
The xsl:import-schema
declaration is used to identify schema components (that is, top-level type
definitions and top-level element and attribute declarations) that need to be
available statically, that is, before any source document is available. Names of such
components used statically within the stylesheet must refer to an in-scope schema component, which means they must either be built-in
types as defined in 3.14 Built-in Types, or they must be imported using
an xsl:import-schema
declaration.
The xsl:import-schema
declaration identifies a namespace containing
the names of the components to be imported (or indicates that components whose names
are in no namespace are to be imported). The effect is that the names of top-level
element and attribute declarations and type definitions from this namespace (or
non-namespace) become available for use within XPath expressions in the package, and within
other stylesheet constructs such as the type
and as
attributes of various XSLT elements.
The same schema components are available in all stylesheet modules within the declaring package; importing components in one stylesheet module makes them available throughout the package.
The schema components imported into different packages within a stylesheet must be consistent. Specifically, it is not permitted to use the same name in the same XSD symbol space to refer to different schema components within different packages; and the union of the schema components imported into the packages of a stylesheet must constitute a valid schema (as well as the set of schema components imported into each package forming a valid schema in its own right).
The namespace
and schema-location
attributes are both
optional.
If the xsl:import-schema
element contains an xs:schema
element, then the schema-location
attribute must be
absent, and one of the following must be true:
the namespace
attribute of the xsl:import-schema
element and the targetNamespace
attribute of the
xs:schema
element are both absent (indicating a no-namespace
schema), or
the namespace
attribute of the xsl:import-schema
element and the targetNamespace
attribute of the
xs:schema
element are both present and both have the same
value, or
the namespace
attribute of the xsl:import-schema
element is absent and the targetNamespace
attribute of the
xs:schema
element is present, in which case the target
namespace is as given on the xs:schema
element.
[ERR XTSE0215] It is a static error if an
xsl:import-schema
element that contains an
xs:schema
element has a schema-location
attribute,
or if it has a namespace
attribute that conflicts with the target
namespace of the contained schema.
If two xsl:import-schema
declarations specify the same namespace, or
if both specify no namespace, then only the one with highest import precedence is used. If this leaves
more than one, then all the declarations at the highest import precedence are used
(which may cause conflicts, as described below).
After discarding any xsl:import-schema
declarations under the above
rule, the effect of the remaining xsl:import-schema
declarations is
defined in terms of a hypothetical document called the synthetic schema document,
which is constructed as follows. The synthetic schema document defines an arbitrary
target namespace that is different from any namespace actually used by the
application, and it contains xs:import
elements corresponding
one-for-one with the xsl:import-schema
declarations in the stylesheet, with the following correspondence:
The namespace
attribute of the xs:import
element is
copied from the namespace
attribute of the
xsl:import-schema
declaration if it is explicitly present,
or is implied by the targetNamespace
attribute of a contained
xs:schema
element, and is absent if it is absent.
The schemaLocation
attribute of the xs:import
element
is copied from the schema-location
attribute of the
xsl:import-schema
declaration if present, and is absent if
it is absent. If there is a contained xs:schema
element, the
effective value of the schemaLocation
attribute is a URI
referencing a document containing a copy of the xs:schema
element.
The base URI of the xs:import
element is the same as the base URI
of the xsl:import-schema
declaration.
The schema components included in the in-scope schema components (that is, the components whose names are available for use within the stylesheet) are the top-level element and attribute declarations and type definitions that are available for reference within the synthetic schema document. See [XML Schema Part 1] (section 4.2.3, References to schema components across namespaces).
[ERR XTSE0220] It is a static error if the synthetic schema document does not satisfy the constraints described in [XML Schema Part 1] (section 5.1, Errors in Schema Construction and Structure). This includes, without loss of generality, conflicts such as multiple definitions of the same name.
Note:
The synthetic schema document does not need to be constructed by a real
implementation. It is purely a mechanism for defining the semantics of
xsl:import-schema
in terms of rules that already exist within
the XML Schema specification. In particular, it implicitly defines the rules that
determine whether the set of xsl:import-schema
declarations are
mutually consistent.
These rules do not cause names to be imported transitively. The fact that a name is available for reference within a schema document A does not of itself make the name available for reference in a stylesheet that imports the target namespace of schema document A. (See [XML Schema Part 1] section 3.15.3, Constraints on XML Representations of Schemas.) The stylesheet must import all the namespaces containing names that it actually references.
The namespace
attribute indicates that a schema for the given
namespace is required by the stylesheet.
This information may be enough on its own to enable an implementation to locate
the required schema components. The namespace
attribute may be
omitted to indicate that a schema for names in no namespace is being imported. The
zero-length string is not a valid namespace URI, and is therefore not a valid
value for the namespace
attribute.
The schema-location
attribute is a URI Reference that gives a hint indicating where a schema document
or other resource containing the required definitions may be found. It is likely
that a schema-aware XSLT
processor will be able to process a schema document found at this
location.
The XML Schema specification gives implementations flexibility in how to handle multiple imports for the same namespace. Multiple imports do not cause errors if the definitions do not conflict.
A consequence of these rules is that it is not intrinsically an error if no schema
document can be located for a namespace identified in an
xsl:import-schema
declaration. This will cause an error only
if it results in the stylesheet containing references to names that have not been
imported.
An inline schema document (using an xs:schema
element as a child of
the xsl:import-schema
element) has the same status as an external
schema document, in the sense that it acts as a hint for a source of schema
components in the relevant namespace. To ensure that the inline schema document is
always used, it is advisable to use a target namespace that is unique to this
schema document.
The use of a namespace in an xsl:import-schema
declaration does not
by itself associate any namespace prefix with the namespace. If names from the
namespace are used within the stylesheet module then a namespace declaration must
be
included in the stylesheet module, in the usual way.
The following example shows an inline schema document. This declares a simple type
local:yes-no
, which the stylesheet then uses in the declaration of
a variable.
The example assumes the namespace declaration
xmlns:local="http://example.com/ns/yes-no"
<xsl:import-schema> <xs:schema targetNamespace="http://example.com/ns/yes-no" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:local="http://example.com/ns/yes-no"> <xs:simpleType name="yes-no"> <xs:restriction base="xs:string"> <xs:enumeration value="yes"/> <xs:enumeration value="no"/> </xs:restriction> </xs:simpleType> </xs:schema> </xsl:import-schema> <xsl:variable name="condition" select="local:yes-no('yes')" as="local:yes-no"/>
There are two built-in functions
(analyze-string
FO30 and json-to-xml
) whose
result is an XML structure for which a schema is defined. The namespace for these
schema definitions is (in both cases) http://www.w3.org/2005/xpath-functions
. Schema
components for these namespaces are available for reference within the stylesheet
if
and only if an xsl:import-schema
declaration is present referencing
this namespace. If such a declaration is present, then the schema that is
imported is the schema defined in the specification of these functions: the schemaLocation
attribute has no effect.