Read XSLT 2.0 and XPath 2.0 Programmer's Reference, 4th Edition Online
Authors: Michael Kay
You can go beyond this, and define a type hierarchy. In a genealogical database, in addition to recording events in a person's life, you can also record properties of a person such as their occupation, religion, state of health, or (if you want) their height or eye color. GEDCOM hasn't modeled these particularly well; it treats them as events, which isn't a particularly good fit. They have a lot in common with events, in that you want to record the evidence for the information, but they tend to be independent of place and to be applicable over some extended period of a person's life. So in an ideal world we would probably model these using a separate type called, say,
ATTRIBUTE
(not to be confused with XML attributes, of course). The things that
EVENT
and
ATTRIBUTE
have in common could be defined in a third type from which both of these inherit: let's call this
DETAIL
. Then in an XPath expression, I can find all the events and all the attributes for a person with the single expression
element(*, DETAIL)
.
Sometimes you get the chance to write a schema with schema-aware XSLT and XQuery processing in mind. More often, however, you have to work with a schema that already exists, and which was written primarily for validation. In this case, it might not contain any very useful type hierarchies. But there's another device in XML Schema that allows elements to be referred to generically, namely substitution groups, and we'll look at what these have to offer in the next section.
Substitution Groups
The type of an element or attribute tells you what can appear inside the content of the element or attribute. Substitution groups, by contrast, classify elements according to where they can appear.
There is a schema for XSLT 2.0 stylesheets published as part of the XSLT Recommendation (see
http://www.w3.org/2007/schema-for-xslt20.xsd
). Let's look at how this schema uses substitution groups.
Firstly, the schema defines a type that is applicable to any XSLT-defined element, and that simply declares the standard attributes that can appear on any element:
type=“xsl:prefix-list-or-all”/>
There's a good mix of features used to define these attributes. Some attributes use built-in types (
xs:anyURI
), while some use user-defined types defined elsewhere in the schema
(xsl:prefixes
). The
Every XSLT element except the
version
attribute (the
version
attribute is defined for a different purpose and has a different type). So the schema defines another type that adds this attribute:
The XSLT specification classifies many XSLT elements as
instructions
. This is not a structural distinction based on the attributes or content model of these elements (which varies widely), it is a distinction based on the way they are used. In particular, instruction elements are interchangeable in terms of where they may appear in a stylesheet: If you can use one instruction in a particular context, you can use any instruction. This calls for defining a substitution group:
type=“xsl:versioned-element-type”
abstract=“true”/>
Note that although the substitution group is defined using an element declaration, it does not define a real element, because it specifies
abstract = “true”
. This means that an actual XSLT stylesheet will never contain an element called
What this declaration does say is that every element in the substitution group for
xsl:versioned-element-type
. That is, every XSLT instruction allows the attributes
default-collation
,
exclude-result-prefixes
,
extension-element-prefixes
,
use-when
,
xpath-default-namespace
, and
version
, as well as any namespace-prefixed attribute. This is in fact the only thing that XSLT instructions have in common with each other, as far as their permitted content is concerned.
Individual instructions are now defined as members of this substitution group. Here is a simple example, the declaration of the
This shows that the
xsl:sequence-constructor
, the extension being to require a
test
attribute whose value is of type
xsl:expression
—this is a simple type defined later in the same schema, representing an XPath expression that may appear as the content of this attribute.
The type
xsl:sequence-constructor
is used for all XSLT elements whose permitted content is a
sequence constructor
. A sequence constructor is simply a sequence of zero or more XSLT instructions, defined like this:
maxOccurs=“unbounded”/>
The first definition says that the
xsl:sequence-constructor
type extends
xsl:versioned-element-type
, whose definition we gave earlier. If it didn't extend this type, we wouldn't be allowed to put
sequence-contructor-group
. The second definition says that every element in
sequence-contructor-group
is either an
The
If you need to use XSLT to access an XSLT stylesheet (which isn't as obscure a requirement as it may seem; there are many applications for this), then the classification of elements as instructions or declarations can be very useful. For example, you can match all the instructions that have an attribute in the Saxon namespace with the template rule:
assuming that the namespace prefix
saxon
has been declared appropriately. Here the expression
schema-element(xsl:instruction)
selects elements that are either named
[@saxon:*]
is a filter that selects only those elements that have an attribute in the
saxon
namespace.