Read XSLT 2.0 and XPath 2.0 Programmer's Reference, 4th Edition Online
Authors: Michael Kay
The next chapter deals with operations involving types: operations that convert a value of one type into a value of another type, and operations that test the type of a value.
Chapter 11
XPath: Type Expressions
This chapter is concerned with XPath expressions that involve types. This includes operations to convert a value of one type to a value of another type (which is called casting), and operations to test whether a value belongs to a particular type.
The type system for XPath was fully explained in Chapter 5. Recall in particular that there are two separate but related sets of types we are concerned with:
We need to use careful language to avoid confusing these two views of the type system. When we have an XPath value that is a node, we will speak of the node being an
instance of
a sequence type—for example, every element is an instance of the sequence type
element()
. At the same time, the node is
annotated with
a schema type—for example, an element node may be annotated as an
mf:invoice
(which will be the name of a complex type defined in some schema).
These two sets of types (sequence types and schema types) overlap: in particular, atomic types such as
xs:integer
belong to both sets. However, list types, union types, and complex types are never used as item types or sequence types; they are used only to annotate nodes. Equally, item types such as
comment()
are only used in sequence types; they are never used to annotate nodes. This idea is illustrated in
Figure 11-1
.
The first part of this chapter is concerned with conversion of values from one type to another. These types are always atomic types; no conversions are defined for any types other than atomic types. The process of atomization, which extracts the typed value of a node, could be regarded as a conversion, but we won't treat it as such for our present purposes.
Atomic types can be referred to by the name given to them in the schema. A schema can define anonymous atomic types, but because these have no name, they can't be referenced in an XPath expression. Named atomic types are always defined by a top-level
name
attribute.
The final part of this chapter deals with two operators (
instance
of
and
treat
as
) that take as their “operands” an arbitrary XPath value (that is, a sequence), and a sequence type. (I've written “operands” in quotes, because a true operand is always a value, and in the XPath view of the world, types are not values). These two constructs require a special syntax for describing sequence types. For example,
attribute(*,
xs:date)?
describes a sequence type whose item type matches any attribute node annotated as an
xs:date
, and whose cardinality allows the sequence to contain zero or one values. I will refer to such a construct as a
sequence type descriptor
, because the construct seems to need a name, and the XPath specification doesn't give it one.
Converting Atomic Values
The operation of converting an atomic value of one type into an atomic value of another type is called casting.
The word
casting
is used with the meaning that it has in SQL, which is subtly different from the usage in many other programming languages. In Java, casts perform a dual role: casting an Object is more like the
treat as
operator described later in this chapter, which doesn't actually change the value from one type to another. But casts in Java are also used for conversions among the primitive types, which is analagous to casting in XPath.
As well as an operator to perform a cast, XPath also provides a second operator to test whether a cast is possible. This has been provided because there is no way of recovering from the error that occurs when a cast fails (if, for example, you convert a string to a date and the string does not contain a valid date). Instead of attempting the cast and then dealing with the error when it fails, XPath encourages you first to test whether it will succeed and then to perform the conversion only if this is the case. So if
$p
is a user-supplied parameter that is supposed to contain a valid date, you can write: