Read XSLT 2.0 and XPath 2.0 Programmer's Reference, 4th Edition Online
Authors: Michael Kay
We will study these operators in much greater depth later in the book.
Sequences also play an important role in navigating trees, as we shall see. The result of a
path expression
such as
/book/chapter/section
is a sequence of nodes. All operators that apply to sequences in general (including those listed above) can therefore be used to manipulate sequences of nodes selected using path expressions.
So, there are two kinds of item that can be found in a sequence, namely atomic values and nodes. We've already studied nodes in some detail in Chapter 2, so now it's time to look at atomic values.
Atomic Values
It's easiest to explain what an atomic value is by example: they are things like integers, floating-point numbers, booleans, and strings.
Every atomic value has a type (it is either an integer, or a string, or a boolean…). Broadly speaking, the types that are available are the 19 primitive types defined in XML Schema, such as
xs:double
,
xs:string
, or
xs:date
, which we will examine in this chapter, and types derived from these.
An atomic value either belongs directly to one of these primitive types, or to a type that is defined by restricting one of these primitive types. This may be a built-in type such as
xs:NMTOKEN
, which is defined in the XML Schema specification itself as a restriction of
xs:string
, or a type defined in a user-written schema. For example, if you have a schema that defines
mf:part-number
as a restriction of
xs:string
, then you can have atomic values whose type is
mf:part-number
.
A type definition determines the set of possible values allowed for items of that type. For example, the type
xs:boolean
has two possible values, called true and false. For a restricted type, the set of possible values is always a subset of the values allowed for its base type. So a type that is defined by restricting
xs:integer
might allow only the values 1 to 20.
An atomic value carries its type with it as a kind of label. If
PY03672
is an
mf:part-number
, then because of the way the type is defined, it is also an
xs:string
. This means it can be used anywhere that an
xs:string
can be used. However, its label still identifies it as an
mf:part-number
. Conversely, if you write the string literal
“PY03672”
in an XPath expression, the value will be labeled as an
xs:string
, and even though it meets all the rules that would make it a valid
mf:part-number
, you cannot use it in places where an
mf:part-number
is required, because it has the wrong label. To create a value labeled as an
mf:part-number
, you need to use the constructor function
mf:part-number(“PY03672”)
.
So the two properties of an atomic value are the value itself, and the type label. If two atomic values are the same in these two respects, then they are indistinguishable. Atomic values do not have any kind of identity separate from their value and their type; there is only one number 42, and only one string “Venice”.
In particular, this means that atomic values are not in any way attached to a particular XML document. Atomic values can be extracted from nodes in an XML document, through a process called
atomization
, described on page 165; but once extracted, they have no residual connection with the document where they originated. Atomic values can also be derived quite independently of any document; for example, as the result of an arithmetic expression.
The full set of primitive atomic types that are available in XPath (that is, types that are not derived by restriction from another type) has been left slightly open-ended. There is an assumption that by default, the 19 primitive types defined in XML Schema will be available. These are:
xs:boolean | xs:date |
xs:decimal | xs:dateTime |
xs:float | xs:time |
xs:double | xs:duration |
xs:string | xs:gYear |
xs:QName | xs:gYearMonth |
xs:anyURI | xs:gMonth |
xs:hexBinary | xs:gMonthDay |
xs:base64Binary | xs:gDay |
xs:NOTATION |