The type system of XPath 4.0 is based on [XML Schema 1.0] or [XML Schema 1.1].
[Definition: A sequence type is a type that can be expressed using the SequenceType syntax. Sequence types are used whenever it is necessary to refer to a type in an XPath 4.0 expression. The term sequence type suggests that this syntax is used to describe the type of an XPath 4.0 value, which is always a sequence.]
[Definition: An item type is a type that can be expressed using the ItemType syntax, which forms part of the SequenceType
syntax. Item types match individual items.]
With the exception of the generic types item()
, which matches all items, and xs:error
,
which matches no items, the set of items matched by an item type consists either
exclusively of atomic values,
exclusively of nodes,
or exclusively of function itemsDM31.
Note:
These definitions require a caveat: types defined in a schema may be anonymous, in which case
they cannot be referenced directly using the ItemType or
SequenceType syntax. For example
an element that is validated against an anonymous complex type A conforms to an item type
which could be written element(*, A)
but for the fact that A is anonymous.
[Definition: A schema type is a type that is (or could be) defined using the facilities of [XML Schema 1.0] or [XML Schema 1.1] (including the built-in types).] A schema type can be used as a type annotation on an
element or attribute node (unless it is a non-instantiable type such as xs:NOTATION
or xs:anyAtomicType
, in which case its derived
types can be so used). Every schema type is either a complex type or a
simple type; simple types are further subdivided into list types, union
types, and atomic types (see [XML Schema 1.0] or [XML Schema 1.1] for definitions and explanations of these terms.)
[Definition: A generalized atomic type is a schema-defined type which is either (a) an atomic type or (b) a pure union type ].
[Definition: A pure union type is an XML Schema union type that satisfies the following constraints:
(1) {variety}
is union
, (2) the {facets}
property is empty, (3) no type in the transitive membership of the union type has {variety}
list
, and (4) no type in the transitive membership of the union type is a type with {variety}
union
having a non-empty {facets}
property].
Note:
The definition of pure union type excludes union types derived by non-trivial restriction from other union types, as well as union types that include list types in their membership. Pure union types have the property that every instance of an atomic type defined as one of the member types of the union is also a valid instance of the union type.
Note:
The current (second) edition of XML Schema 1.0 contains an error in respect of the substitutability of a union type by one of its members: it fails to recognize that this is unsafe if the union is derived by restriction from another union.
This problem is fixed in XSD 1.1, but the effect of the resolution is that an atomic value labeled with an atomic type cannot be treated as being substitutable for a union type without explicit validation. This specification therefore allows union types to be used as item types only if they are defined directly as the union of a number of atomic types.
Generalized atomic types
represent the intersection between the categories of sequence type and schema type. A generalized atomic type, such as xs:integer
or my:hatsize
, is both a sequence type and a
schema type.
The in-scope schema types
in the static
context are initialized with a set of
predefined schema types that is determined by the host
language. This set may include some or all of the
schema types in the
namespace
http://www.w3.org/2001/XMLSchema
,
represented in this document by the namespace prefix
xs
. The schema types in this namespace are defined in [XML Schema 1.0] or [XML Schema 1.1]
and augmented by additional types defined in [XQuery and XPath Data Model (XDM) 3.1]. An implementation
that has based its type system on [XML Schema 1.0] is not required to support the xs:dateTimeStamp
or xs:error
types.
The schema types defined in Section 2.7.2 Predefined Types DM31 are summarized below.
[Definition:
xs:untyped
is used as the type annotation of an element node that has not been validated, or has been validated in skip
mode.] No predefined schema types are derived from xs:untyped
.
[Definition:
xs:untypedAtomic
is an atomic type that is used to denote untyped atomic data, such as text that has not been assigned a more specific type.] An attribute that has been validated in skip
mode is represented in the data model by an attribute node with the type annotation
xs:untypedAtomic
. No predefined schema types are derived from xs:untypedAtomic
.
[Definition:
xs:dayTimeDuration
is derived by restriction from xs:duration
. The lexical representation of xs:dayTimeDuration
is restricted to contain only day, hour, minute, and second
components.]
[Definition:
xs:yearMonthDuration
is derived by restriction from xs:duration
. The lexical representation of xs:yearMonthDuration
is
restricted to contain only year and month
components.]
[Definition:
xs:anyAtomicType
is an atomic type that includes all atomic values (and no values that
are not atomic). Its base type is
xs:anySimpleType
from which all simple types, including atomic,
list, and union types, are derived. All primitive atomic types, such as
xs:decimal
and xs:string
, have xs:anyAtomicType
as their base type.]
Note:
xs:anyAtomicType
will not appear as the type of an actual value in an XDM instance.
[Definition:
xs:error
is a simple type with no value space. It is defined in Section
3.16.7.3 xs:error
XS11-1 and can be used in the 3.4 Sequence Types to raise errors.]
The relationships among the schema types in the xs
namespace are illustrated in Figure 2. A more complete description of the XPath 4.0 type hierarchy can be found in
Section
1.6 Type System
FO31.
Figure 2: Hierarchy of Schema Types used in XPath 4.0.
[Definition: The namespace-sensitive
types are xs:QName
, xs:NOTATION
, types
derived by restriction from xs:QName
or
xs:NOTATION
, list types that have a namespace-sensitive
item type, and union types with a namespace-sensitive type in their
transitive membership.]
It is not possible to preserve the type of a namespace-sensitive value without also preserving the namespace binding that defines the meaning of each namespace prefix used in the value. Therefore, XPath 4.0 defines some error conditions that occur only with namespace-sensitive values. For instance, casting to a namespace-sensitive type raises a type error [err:FONS0004]FO31 if the namespace bindings for the result cannot be determined.
Every node has a typed value and a string value, except for nodes whose value is absentDM31. [Definition: The typed value of a node is a sequence of atomic values and can be extracted by applying the Section 2.4 fn:data FO31 function to the node.] [Definition: The string value of a node is a string and can be extracted by applying the Section 2.3 fn:string FO31 function to the node.]
An implementation may store both the typed value and the string value of a node, or it may store only one of these and derive the other as needed. The string value of a node must be a valid lexical representation of the typed value of the node, but the node is not required to preserve the string representation from the original source document. For example, if the typed value of a node is the xs:integer
value 30
, its string value might be "30
" or "0030
".
The typed value, string value, and type annotation of a node are closely related. If the node was created by mapping from an Infoset or PSVI, the relationships among these properties are defined by rules in Section 2.7 Schema Information DM31.
As a convenience to the reader, the relationship between typed value and string value for various kinds of nodes is summarized and illustrated by examples below.
For text and document nodes, the typed value of the node is the same as its
string value, as an instance of the type xs:untypedAtomic
. The
string value of a document node is formed by concatenating the string
values of all its descendant text nodes, in document
order.
The typed value of a comment, namespace, or processing instruction node is the same as its string value. It is an instance of the type xs:string
.
The typed value of an attribute node with
the type annotation
xs:anySimpleType
or xs:untypedAtomic
is the same as its
string value, as an instance of xs:untypedAtomic
. The
typed value of an attribute node with any other type annotation is
derived from its string value and type annotation using the lexical-to-value-space mapping defined in [XML Schema 1.0] or [XML Schema 1.1] Part 2 for
the relevant type.
Example: A1 is an attribute
having string value "3.14E-2"
and type annotation
xs:double
. The typed value of A1 is the
xs:double
value whose lexical representation is
3.14E-2
.
Example: A2 is an attribute with type
annotation xs:IDREFS
, which is a list datatype whose item type is the atomic datatype xs:IDREF
. Its string value is
"bar baz faz
". The typed value of A2 is a sequence of
three atomic values ("bar
", "baz
",
"faz
"), each of type xs:IDREF
. The typed
value of a node is never treated as an instance of a named list
type. Instead, if the type annotation of a node is a list type (such
as xs:IDREFS
), its typed value is treated as a sequence
of the generalized atomic type from which it is derived (such as
xs:IDREF
).
For an element node, the relationship between typed value and string value depends on the node's type annotation, as follows:
If the type annotation is xs:untyped
or xs:anySimpleType
or
denotes a complex type with mixed content (including xs:anyType
), then the typed value of the
node is equal to its string value, as an instance of
xs:untypedAtomic
. However, if the nilled
property of the node is true
, then its typed value is the empty sequence.
Example: E1 is an element node
having type annotation xs:untyped
and string value
"1999-05-31
". The typed value of E1 is
"1999-05-31
", as an instance of
xs:untypedAtomic
.
Example: E2 is an element node
with the type annotation formula
, which is a complex type
with mixed content. The content of E2 consists of the character
"H
", a child element named subscript
with
string value "2
", and the character "O
". The
typed value of E2 is "H2O
" as an instance of
xs:untypedAtomic
.
If the type
annotation denotes a simple type or a complex type with simple
content, then the typed value of the node is derived from its string
value and its type annotation in a way that is consistent with schema
validation. However, if the nilled
property of the node is true
, then its typed value is the empty sequence.
Example: E3 is an element node with the type
annotation cost
, which is a complex type that has several
attributes and a simple content type of xs:decimal
. The
string value of E3 is "74.95
". The typed value of E3 is
74.95
, as an instance of
xs:decimal
.
Example: E4 is an element node with the
type annotation hatsizelist
, which is a simple type
derived from the atomic type hatsize
, which in turn is
derived from xs:integer
. The string value of E4 is
"7 8 9
". The typed value of E4 is a sequence of three
values (7
, 8
, 9
), each of type
hatsize
.
Example: E5 is an element node with the type annotation my:integer-or-string
which is a union type with member types xs:integer
and xs:string
. The string value of E5 is "47
". The typed value of E5 is 47
as an xs:integer
, since xs:integer
is the member type that validated the content of E5. In general, when the type annotation of a node is a union type, the typed value of the node will be an instance of one of the member types of the union.
Note:
If an implementation stores only the string value of a node, and the type annotation of the node is a union type, the implementation must be able to deliver the typed value of the node as an instance of the appropriate member type.
If the type annotation denotes a complex type with empty content, then the typed value of the node is the empty sequence and its string value is the zero-length string.
If the type annotation
denotes a complex type with element-only content, then the typed value
of the node is absentDM31. The fn:data
function raises a
type error
[err:FOTY0012]FO31 when applied to such a node. The string value of such a node is equal to the concatenated string values of all its text node descendants, in document order.
Example: E6 is an
element node with the type annotation weather
, which is a
complex type whose content type specifies
element-only
. E6 has two child elements named
temperature
and precipitation
. The typed
value of E6 is absentDM31, and the fn:data
function
applied to E6 raises an error.
Whenever it is necessary to refer to a type in an XPath 4.0 expression, the SequenceType syntax is used.
[95] | SequenceType |
::= | ("empty-sequence" "(" ")") |
|
[97] | ItemType |
::= |
AnyItemTest | TypeName | KindTest | FunctionTest | MapTest | ArrayTest | AtomicOrUnionType | RecordTest | LocalUnionType | EnumerationType | ParenthesizedItemType
|
|
[96] | OccurrenceIndicator |
::= | "?" | "*" | "+" |
/* xgc: occurrence-indicators */ |
With the exception of the special type
empty-sequence()
, a sequence type consists of an
item type that constrains the type of each item in the
sequence, and a cardinality that constrains the number of
items in the sequence. Apart from the item type item()
,
which permits any kind of item, item types divide into node
types (such as element()
), generalized atomic
types (such as xs:integer
) and function types
(such as function() as item()*).
Lexical QNames appearing in a sequence type have their
prefixes expanded to namespace URIs by means of the
statically known namespaces and (where applicable) the
default element namespace
or default type namespace
.
Equality of QNames is defined by the eq
operator.
Item types representing element
and attribute nodes may specify the required type annotations of those nodes, in
the form of a schema
type. Thus the item type element(*, us:address)
denotes any element node whose type annotation is (or is derived from)
the schema type named us:address
.
The occurrence indicators '+', '*', and '?' bind to the last ItemType in the SequenceType, as described in occurrence-indicators constraint.
Here are some examples of sequence types that might be used in XPath 4.0:
xs:date
refers to the built-in atomic schema type named xs:date
attribute()?
refers to an optional attribute node
element()
refers to any element node
element(po:shipto, po:address)
refers to an element node that has the name po:shipto
and has the type annotation po:address
(or a schema type derived from po:address
)
element(*, po:address)
refers to an element node of any name that has the type annotation po:address
(or a type derived from po:address
)
element(customer)
refers to an element node named customer
with any type annotation
schema-element(customer)
refers to an element node whose name is customer
(or is in the substitution group headed by customer
) and whose type annotation matches the schema type declared for a customer
element in the in-scope element declarations
node()*
refers to a sequence of zero or more nodes of any kind
item()+
refers to a sequence of one or more items
function(*)
refers to any function item, regardless of arity or type
function(node()) as xs:string*
refers to a function item that takes a single argument whose value is a single node,
and returns a sequence of zero or more xs:string
values
(function(node()) as xs:string)*
refers to a sequence of zero or more function items, each of which takes a single
argument whose value is a single node, and returns as its result a single xs:string
value
[Definition:
SequenceType matching compares a value with an expected sequence type. ] For example, an instance of
expression
returns true
if a given value matches a given sequence type, or false
if it does not.
An XPath 4.0 implementation must be able to determine relationships among the types in type annotations in an XDM instance and the types in the in-scope schema definitions (ISSD).
[Definition: The use of a value that has a dynamic type
that is a subtype of the
expected type is known as subtype substitution.]
Subtype substitution does not change the actual type of a value. For
example, if an xs:integer
value is used where an
xs:decimal
value is expected, the value retains its type
as xs:integer
.
The definition of SequenceType matching relies
on a pseudo-function named derives-from(
AT,
ET
)
, which takes an actual simple or complex
schema type AT and an expected simple or complex schema
type ET, and either returns a boolean value or raises a
type error
[err:XPTY0004]. This function is defined as follows:
derives-from(
AT, ET
)
raises a type error [err:XPTY0004] if ET is
not present in the in-scope schema definitions (ISSD).
derives-from(
AT,
ET
)
returns true
if any of the following conditions applies:
AT is ET
ET is the base type of AT
ET is a pure union type of which AT is a member type
There is a type MT such that derives-from(
AT, MT
)
and derives-from(
MT, ET
)
Otherwise, derives-from(
AT, ET
)
returns false
The rules for SequenceType matching are given below, with examples (the examples are for purposes of illustration, and do not cover all possible cases).
The sequence type
empty-sequence()
matches a value that is the empty sequence.
An ItemType with no OccurrenceIndicator matches any value that contains exactly one item if the ItemType matches that item (see 3.6 Item Types).
An ItemType with an OccurrenceIndicator matches a value if the number of items in the value matches the OccurrenceIndicator and the ItemType matches each of the items in the value.
An OccurrenceIndicator specifies the number of items in a sequence, as follows:
?
matches zero or one items
*
matches zero or more items
+
matches one or more items
As a consequence of these rules, any sequence type whose
OccurrenceIndicator is *
or ?
matches a
value that is an empty sequence.
[97] | ItemType |
::= |
AnyItemTest | TypeName | KindTest | FunctionTest | MapTest | ArrayTest | AtomicOrUnionType | RecordTest | LocalUnionType | EnumerationType | ParenthesizedItemType
|
|
[98] | AnyItemTest |
::= | "item" "(" ")" |
|
[116] | TypeName |
::= |
EQName
|
|
[100] | KindTest |
::= |
DocumentTest
|
|
[102] | DocumentTest |
::= | "document-node" "(" (ElementTest | SchemaElementTest)? ")" |
|
[110] | ElementTest |
::= | "element" "(" (NameTest ("," TypeName "?"?)?)? ")" |
|
[111] | SchemaElementTest |
::= | "schema-element" "(" ElementDeclaration ")" |
|
[112] | ElementDeclaration |
::= |
ElementName
|
|
[107] | AttributeTest |
::= | "attribute" "(" (NameTest ("," TypeName)?)? ")" |
|
[108] | SchemaAttributeTest |
::= | "schema-attribute" "(" AttributeDeclaration ")" |
|
[109] | AttributeDeclaration |
::= |
AttributeName
|
|
[114] | ElementName |
::= |
EQName
|
|
[113] | AttributeName |
::= |
EQName
|
|
[106] | PITest |
::= | "processing-instruction" "(" (NCName | StringLiteral)? ")" |
|
[104] | CommentTest |
::= | "comment" "(" ")" |
|
[105] | NamespaceNodeTest |
::= | "namespace-node" "(" ")" |
|
[103] | TextTest |
::= | "text" "(" ")" |
|
[101] | AnyKindTest |
::= | "node" "(" ")" |
|
[117] | FunctionTest |
::= |
AnyFunctionTest
|
|
[118] | AnyFunctionTest |
::= | "function" "(" "*" ")" |
|
[119] | TypedFunctionTest |
::= | "function" "(" (SequenceType ("," SequenceType)*)? ")" "as" SequenceType
|
|
[133] | ParenthesizedItemType |
::= | "(" ItemType ")" |
|
[120] | MapTest |
::= |
AnyMapTest | TypedMapTest
|
|
[123] | RecordTest |
::= | "record" "(" FieldDeclaration ("," FieldDeclaration)* ExtensibleFlag? ")" |
|
[130] | ArrayTest |
::= |
AnyArrayTest | TypedArrayTest
|
|
[99] | AtomicOrUnionType |
::= |
EQName
|
|
[128] | LocalUnionType |
::= | "union" "(" ItemType ("," ItemType)* ")" |
|
[129] | EnumerationType |
::= | "enum" "(" StringLiteral ("," StringLiteral)* ")" |
This section defines the semantics of different ItemTypes
in terms of the values that they match.
An item type written simply as an EQName
(that is, a NamedType
) is interpreted as follows:
If the name is written as a lexical QName, then it is expanded using the
in-scope namespaces in the static context. If the
name is an unprefixed NCName
, then it is taken as being in the
default type namespace.
If the name matches an entry in the item type aliases in the static context, then it is taken as a reference to the corresponding item type. The rules that apply are the rules for the expanded item type definition.
Otherwise, it must match the name of a type in the in-scope schema types in the static context: specifically, an atomic type or a plain union type. See 3.6.2 Atomic and Union Types for details.
Note:
A name in the xs
namespace will always fall into this category, since the namespace
is reserved.
If the name cannot be resolved to a type, a static error is raised [err:XPST0051].
item()
matches
any single item.
Example: item()
matches the atomic
value 1
, the element <a/>
, or the function fn:concat#3
.
A ParenthesizedItemType matches an item if and only if the item matches the ItemType that is in parentheses.
Note:
Parenthesized item types are used primarily when defining nested item types in a function
signature: for example a sequence of functions that return booleans might be denoted
(function () as xs:boolean)*
. In this example the parentheses
are needed to indicate where the occurrence indicator belongs.
A generalized atomic type may be expressed as an ItemType in any of the following ways:
Using the QName of a type in the in-scope schema definitions that is an atomic type or a pure union type
Using a QName that identifies a type alias that resolves to a generalized atomic type.
Using a ParenthesizedItemType where the parentheses enclose a generalized atomic type.
Using a LocalUnionType as described below.
Using an EnumerationType as described below.
Example: The ItemType
xs:decimal
matches any value of type
xs:decimal
. It also matches any value of type
shoesize
, if shoesize
is an atomic type
derived by restriction from xs:decimal
.
Example: Suppose ItemType
dress-size
is a union type that allows
either xs:decimal
values for numeric sizes (e.g. 4, 6, 10, 12),
or one of an enumerated set of xs:strings
(e.g. "small", "medium", "large"). The ItemType
dress-size
matches any of these values.
Note:
The names of list
types such as xs:IDREFS
are not accepted in this context,
but can often be replaced by a generalized atomic type with an occurrence indicator, such as
xs:IDREF+
.
A LocalUnionType
defines an anonymous union type locally (for example,
within a function signature) which may be more convenient than defining the type in an
imported schema.
[128] | LocalUnionType |
::= | "union" "(" ItemType ("," ItemType)* ")" |
Although the grammar allows any ItemType
to appear, each ItemType
must identify a generalized atomic type. [TODO: error code]
An item matches a LocalUnionType
if it matches any of the
generalized atomic types
listed within the parentheses.
For example, the type union(xs:date, xs:dateTime, xs:time)
matches any value that is an instance
of xs:date
, xs:dateTime
, or xs:time
.
Similarly, the type union(xs:NCName, enum(""))
matches any value that is either
an instance of xs:NCName
, or a zero-length string. This might be a suitable type for
a variable that holds a namespace prefix.
Note:
Local union types are particularly useful in function signatures, allowing a function to take arguments of a variety of types. The semantics are identical to using a named union type, but a local union type is more convenient because it does not need to be defined in a schema, and does not require a schema-aware processor.
A local union type can also be used in a cast expression: cast @when as union(xs:date, xs:dateTime)
allows the attribute @when
to be either a date, or a dateTime.
An instance of
expression can be used to test whether a value belongs to one
of a number of specified types: $x instance of union(xs:string, xs:anyURI, xs:untypedAtomic)
returns true if $x
is an instance of any of these three atomic types.
[Definition: An EnumerationType accepts a fixed set of string values.]
[129] | EnumerationType |
::= | "enum" "(" StringLiteral ("," StringLiteral)* ")" |
An item matches an EnumerationType
if it is an instance of xs:string
,
and is equal to one of the string literals listed within the parentheses, when compared
using the codepoint collation.
For example, the type enum("red", "green", "blue")
matches the string "green".
Note:
Unlike a schema-defined type that restricts xs:string
with an enumeration facet,
matching of an EnumerationType
is based purely on value comparison, and not on type
annotations. For example, if color
is a schema-defined atomic type derived from
xs:string
with an enumeration facet permitting the values ("red", "green", "blue"),
the expression "green" instance of color
is false, because the type annotation
does not match. By contrast, "green" instance of enum("red", "green", "blue")
is true.
An EnumerationType only matches xs:string
values, not
xs:untypedAtomic
or xs:anyURI
values, even though these might compare
equal. However, the coercion rules allow xs:untypedAtomic
or
xs:anyURI
values to be supplied where the required type is an enumeration type.
Some of the constructs described in this section include a TypeName. This appears as T in:
element(N, T)
attribute(N, T)
document-node(element(N, T))
In these constructs, the type name T is expanded using the in-scope namespaces
in the static context, using the default type namespace if it is unprefixed. The resulting
QName must identify a type in the in-scope schema definitions. This can be any schema type: either a simple type,
or (except in the case of attributes) a complex type. If it is a simple type then it can be an atomic, union, or
list type. It can be a built-in type (such as xs:integer
) or a user-defined type. It must however
be the name of a type defined in a schema; it cannot be a type alias.
node()
matches any node.
text()
matches any
text node.
processing-instruction()
matches any processing-instruction
node.
processing-instruction(
N
)
matches any processing-instruction node whose PITarget is equal to fn:normalize-space(N)
. If fn:normalize-space(N)
is not in the lexical space of NCName, a type error is raised [err:XPTY0004]
Example:
processing-instruction(xml-stylesheet)
matches any
processing instruction whose PITarget is
xml-stylesheet
.
For backward compatibility with
XPath 1.0, the PITarget of a
processing instruction may also be expressed as a
string literal, as in this example:
processing-instruction("xml-stylesheet")
.
If the specified PITarget is not a syntactically valid NCName, a type error is raised [err:XPTY0004].
comment()
matches any comment node.
namespace-node()
matches any
namespace node.
document-node()
matches any document
node.
document-node(
E
)
matches any document node that contains exactly one element node, optionally accompanied by one or more comment and processing instruction nodes, if
E is an ElementTest or SchemaElementTest that matches the element node (see
3.6.3.2 Element Test and 3.6.3.3 Schema Element Test).
Example:
document-node(element(book))
matches a document node
containing
exactly one element node that is matched by the ElementTest
element(book)
.
An ItemType that is an ElementTest, SchemaElementTest, AttributeTest, SchemaAttributeTest, or FunctionTest matches an item as described in the following sections.
[110] | ElementTest |
::= | "element" "(" (NameTest ("," TypeName "?"?)?)? ")" |
|
[58] | NameTest |
::= |
EQName | Wildcard
|
|
[114] | ElementName |
::= |
EQName
|
|
[116] | TypeName |
::= |
EQName
|
An ElementTest is used to match an element node by its name and/or type annotation.
The ElementName and TypeName of an ElementTest have their prefixes expanded to namespace URIs by means of the statically known namespaces, or if unprefixed, the default element namespace or default type namespace respectively. The ElementName need not be present in the in-scope element declarations, but the TypeName must be present in the in-scope schema types [err:XPST0008]. Note that substitution groups do not affect the semantics of ElementTest.
An ElementTest may take any of the following forms:
element()
and
element(*)
match any
single element node, regardless of its name or
type annotation.
element(
ElementName
)
matches any element node whose name is ElementName, regardless of its type annotation or nilled
property.
Example: element(person)
matches any element node whose name is person
.
element(prefix:*)
matches any element node whose name is in the namespace bound to the given prefix, regardless of its type annotation or nilled
property.
Example: element(xhtml:*)
matches any element node whose name is in the namespace
bound to the prefix xhtml
.
element(Q{uri}*)
matches any element node whose name is in the namespace given as uri
, regardless of its type annotation or nilled
property.
Example: element(Q{"http://www.w3.org/2000/svg"}*)
matches any element node whose name is in the SVG namespace.
element(*:local)
matches any element node whose local name is the name given as local
, regardless of its namespace,
type annotation or nilled
property.
Example: element(*:html)
matches any element node whose local name is "html".
element(
ElementName
,
TypeName
)
matches an element node whose name is ElementName if derives-from(
AT, TypeName
)
is true
, where AT is the type annotation of the element node, and the nilled
property of the node is false
.
Example: element(person, surgeon)
matches a
non-nilled element node whose name is person
and whose
type annotation is surgeon
(or is derived from surgeon
).
The ElementName
in this example can also be replaced by one of the forms
prefix:*
, Q{uri}*
, or *:local
.
element(
ElementName, TypeName
?)
matches an element node whose name is ElementName if derives-from(
AT, TypeName
)
is true
, where AT is the type annotation of the element node. The nilled
property of the node may be either true
or false
.
Example: element(person, surgeon?)
matches a nilled or non-nilled element node whose name is person
and whose type
annotation is surgeon
(or is derived from surgeon
).
The ElementName
in this example can also be replaced by one of the forms
prefix:*
, Q{uri}*
, or *:local
.
element(*,
TypeName
)
matches an element
node regardless of its name, if
derives-from(
AT, TypeName
)
is
true
, where AT is the type annotation of the element node, and the nilled
property of the node is false
.
Example: element(*, surgeon)
matches any non-nilled element node whose type annotation is
surgeon
(or is derived from surgeon
), regardless of its name.
element(*,
TypeName
?)
matches an element
node regardless of its name, if
derives-from(
AT, TypeName
)
is
true
, where AT is the type annotation of the element node. The nilled
property of the node may be either true
or false
.
Example: element(*, surgeon?)
matches any nilled or non-nilled element node whose type annotation is
surgeon
(or is derived from surgeon
), regardless of its name.
[111] | SchemaElementTest |
::= | "schema-element" "(" ElementDeclaration ")" |
|
[112] | ElementDeclaration |
::= |
ElementName
|
|
[114] | ElementName |
::= |
EQName
|
A SchemaElementTest matches an element node against a corresponding element declaration found in the in-scope element declarations.
The ElementName of a SchemaElementTest has its prefixes expanded to a namespace URI by means of the statically known namespaces, or if unprefixed, the default element namespace . If the ElementName specified in the SchemaElementTest is not found in the in-scope element declarations, a static error is raised [err:XPST0008].
A SchemaElementTest matches a candidate element node if all of the following conditions are satisfied:
Either:
The name N of the candidate node matches the specified ElementName, or
The name N of the candidate node matches the name of an element declaration that is a member of the actual substitution group headed by the declaration of element ElementName.
Note:
The term "actual substitution group" is defined in [XML Schema 1.1]. The actual substitution group of an element declaration H includes those element declarations P that are declared to have H as their direct or indirect substitution group head, provided that P is not declared as abstract, and that P is validly substitutable for H, which means that there must be no blocking constraints that prevent substitution.
The schema element declaration named N is not abstract.
derives-from( AT, ET )
is true, where AT is the type annotation of the candidate node and ET is the schema type declared in the schema element declaration named N.
If the schema element declaration named N is not nillable, then the nilled property of the candidate node is false.
Example: The SchemaElementTest
schema-element(customer)
matches a candidate element node
in the following two situations:
customer is a top-level element declaration in the in-scope element declarations; the name of the candidate node is customer; the element declaration of customer is not abstract; the type annotation of the candidate node is the same as or derived from the schema type declared in the customer element declaration; and either the candidate node is not nilled, or customer is declared to be nillable.
customer is a top-level element declaration in the in-scope element declarations; the name of the candidate node is client; client is an actual (non-abstract and non-blocked) member of the substitution group of customer; the type annotation of the candidate node is the same as or derived from the schema type declared for the client element; and either the candidate node is not nilled, or client is declared to be nillable.
[107] | AttributeTest |
::= | "attribute" "(" (NameTest ("," TypeName)?)? ")" |
|
[58] | NameTest |
::= |
EQName | Wildcard
|
|
[113] | AttributeName |
::= |
EQName
|
|
[116] | TypeName |
::= |
EQName
|
An AttributeTest is used to match an attribute node by its name and/or type annotation.
The AttributeName and TypeName of an AttributeTest have their prefixes expanded to namespace URIs by means of the statically known namespaces. If unprefixed, the AttributeName is in no namespace, but an unprefixed TypeName is in the default type namespace . The AttributeName need not be present in the in-scope attribute declarations, but the TypeName must be present in the in-scope schema types [err:XPST0008].
An AttributeTest may take any of the following forms:
attribute()
and attribute(*)
match any single attribute node,
regardless of its name or type annotation.
attribute(
AttributeName
)
matches any attribute node whose name is AttributeName, regardless of its type annotation.
Example: attribute(price)
matches any attribute node whose name is price
.
attribute(prefix:*)
matches any attribute node whose name is in the namespace bound to the given prefix, regardless of its type annotation.
Example: attribute(xlink:*)
matches any attribute node whose name is in the namespace
bound to the prefix xlink
.
attribute(Q{uri}*)
matches any attribute node whose name is in the namespace given as uri
, regardless of its type annotation.
Example: element(Q{"http://www.w3.org/2000/svg"}*)
matches any attribute node whose name is in the SVG namespace.
attribute(*:local)
matches any attribute node whose local name is the name given as local
, regardless of its namespace or
type annotation.
Example: attribute(*:default-collation)
matches any attribute node whose local name is "default-collation".
attribute(
AttributeName, TypeName
)
matches an attribute node whose name is AttributeName if derives-from(
AT, TypeName
)
is true
, where AT is the type annotation of the attribute node.
Example: attribute(price, currency)
matches an
attribute node whose name is price
and whose type
annotation is
currency
(or is derived from currency
).
The AttributeName
in this example can also be replaced by one of the forms
prefix:*
, Q{uri}*
, or *:local
.
attribute(*,
TypeName
)
matches an attribute
node regardless of its name, if
derives-from(
AT, TypeName
)
is
true
, where AT is the type annotation of the attribute node.
Example:
attribute(*, currency)
matches any attribute node whose
type annotation is currency
(or is derived from currency
), regardless of its
name.
[108] | SchemaAttributeTest |
::= | "schema-attribute" "(" AttributeDeclaration ")" |
|
[109] | AttributeDeclaration |
::= |
AttributeName
|
|
[113] | AttributeName |
::= |
EQName
|
A SchemaAttributeTest matches an attribute node against a corresponding attribute declaration found in the in-scope attribute declarations.
The AttributeName of a SchemaAttributeTest has its prefixes expanded to a namespace URI by means of the statically known namespaces. If unprefixed, an AttributeName is in no namespace. If the AttributeName specified in the SchemaAttributeTest is not found in the in-scope attribute declarations, a static error is raised [err:XPST0008].
A SchemaAttributeTest matches a candidate attribute node if both of the following conditions are satisfied:
The name of the candidate node matches the specified AttributeName.
derives-from(
AT, ET
)
is true
, where AT is the type annotation of the candidate node and ET is the schema type declared for attribute AttributeName in the in-scope attribute declarations.
Example: The SchemaAttributeTest
schema-attribute(color)
matches a candidate attribute node if color
is a top-level attribute declaration in the in-scope attribute declarations, the name of the candidate node is color
, and the type annotation of the candidate node is the same as or derived from the schema type declared for the color
attribute.
The following sections describe the syntax for item types for function, including arrays and maps.
The subtype relation among these types is described in the various subsections of 3.7.2 Subtypes of Item Types.
[117] | FunctionTest |
::= |
AnyFunctionTest
|
|
[118] | AnyFunctionTest |
::= | "function" "(" "*" ")" |
|
[119] | TypedFunctionTest |
::= | "function" "(" (SequenceType ("," SequenceType)*)? ")" "as" SequenceType
|
A FunctionTest matches a function item, potentially also checking its function signatureDM31 . An AnyFunctionTest matches any item that is a function. A TypedFunctionTest matches an item if it is a function and the function's type signature (as defined in Section 2.8.1 Functions DM31) is a subtype of the TypedFunctionTest.
Here are some examples of FunctionTests:
function(*)
matches any function, including maps and arrays.
function(int, int) as int
matches any function item with the function signature function(int, int) as int
.
function(xs:anyAtomicType) as item()*
matches any map, or any function with the required signature.
function(xs:integer) as item()*
matches any array, or any function with the required signature.
[120] | MapTest |
::= |
AnyMapTest | TypedMapTest
|
|
[121] | AnyMapTest |
::= | "map" "(" "*" ")" |
|
[122] | TypedMapTest |
::= | "map" "(" ItemType "," SequenceType ")" |
The MapTest
map(*)
matches any map. The MapTest
map(X, Y)
matches any map where the type of every key
is an instance of X
and the type of every value is an
instance of Y
.
Although the grammar for TypedMapTest
allows the key to be described using the full ItemType
syntax, the item type used must be
a generalized atomic type. [TODO: error code].
Examples:
Given a map $M
whose keys are integers and whose
results are strings, such as map{0:"no", 1:"yes"}
,
consider the results of the following expressions:
$M instance of map(*)
returns true()
$M instance of map(xs:integer, xs:string)
returns true()
$M instance of map(xs:decimal, xs:anyAtomicType)
returns true()
not($M instance of map(xs:int, xs:string))
returns true()
not($M instance of map(xs:integer, xs:token))
returns true()
Because of the rules for subtyping of function types according to their signature, it follows that the item type
function(A) as item()*
, where A is an atomic type, also matches any map, regardless of the type of the keys actually
found in the map. For example, a map whose keys are all strings can be supplied where the required type is
function(xs:integer) as item()*
; a call on the map that treats it as a function with an integer argument will always succeed,
and will always return an empty sequence.
The function signature of a map matching type
map(K, V)
, treated as a function, is
function(xs:anyAtomicType) as V?
. It is thus always a
subtype of function(xs:anyAtomicType) as item()*
regardless of the
actual types of the keys and values in the map. The rules for
function coercion mean that any map can be supplied as a value in a
context where the required type has a more specific return type,
such as function(xs:anyAtomicType) as xs:integer
, even when the map
does not match in the sense required to satisfy the instance of
operator. In such cases, a type error will only occur if an actual
call on the map (treated as a function) returns a value that is not
an instance of the required return type.
Examples:
$M instance of function(*)
returns true()
$M instance of function(xs:anyAtomicType) as item()*
returns true()
$M instance of function(xs:integer) as item()*
returns true()
$M instance of function(xs:int) as item()*
returns true()
$M instance of function(xs:string) as item()*
returns true()
not($M instance of function(xs:integer) as xs:string)
returns true()
Note:
The last case might seem surprising;
however, function coercionn ensures that $M
can be used successfully
anywhere that the required type is function(xs:integer) as xs:string
.
Rules defining whether one map type is a subtype of another are given in 3.7.2.7 Maps.
[123] | RecordTest |
::= | "record" "(" FieldDeclaration ("," FieldDeclaration)* ExtensibleFlag? ")" |
|
[124] | FieldDeclaration |
::= |
FieldName "?"? ("as" (SequenceType | SelfReference))? |
|
[125] | FieldName |
::= |
NCName | StringLiteral
|
|
[126] | SelfReference |
::= | ".." OccurrenceIndicator? |
|
[127] | ExtensibleFlag |
::= | "," "*" |
A RecordTest matches maps that meet specific criteria.
For example, the RecordTest
record(r as xs:double, i as xs:double)
matches a map if the map has exactly two entries: an entry with key "r"
whose value is a singleton xs:double
value, and an entry with key "i"
whose value is also a singleton xs:double
value.
If the list of fields ends with ",*"
then the record test is said to be
extensible. For example, the RecordTest
record(e as element(Employee), *)
matches a map if it has an entry with key "e"
whose value matches element(Employee)
,
regardless what other entries the map might contain.
A record test can only constrain entries whose keys are strings, but when the record test is marked as extensible, then other entries may be present in the map with non-string keys. Entries whose key is a string can be expressed using an (unquoted) NCName if the key conforms to NCName syntax, or using a (quoted) string literal otherwise.
Note:
Lookup expressions have been extended so that non-NCName keys can be used without
parentheses: employee?"middle name"
If the type declaration for a field is omitted, then item()*
is assumed: that is,
the map entry may have any type.
If the field name is followed by a question mark,
then the value must have the specified type if it is present, but it may also be absent. For example,
the RecordTest
record(first as xs:string, middle? as xs:string, last as xs:string, *)
requires the map to have string-valued entries with keys "first"
and "last"
;
it also declares that if the map has an entry with key "middle"
, the value of that
entry must be a single xs:string
. Declaring the type as
record(first as xs:string, middle? as xs:string?, last as xs:string, *)
also allows
the entry with key "middle"
to be present but empty.
Note:
Within an extensible record test, a FieldDeclaration
that is marked optional
and has no declared type does not constrain the
map in any way, so it serves no practical purpose, but it is permitted because it may have
documentary value.
If a field is declared using ..
(optionally followed
by an occurrence indicator) in place of a SequenceType
,
this indicates that the record type is recursive: the value
of this field, if present, must be an instance of the record type being declared. For example, a record
designed to hold error information might be declared as:
record(error-code as xs:QName, message as xs:string, cause? as ..)
A map conforms to this type if it has entries with keys error-code
and message
of the correct types, and if the cause
entry is either absent, or is a map that itself conforms
to this type.
A FieldDeclaration
that a SelfReference
to identify its type must either
be optional (marked with a question mark after the name), or must allow the empty sequence as a permitted
value (marked by using the occurrence indicator ?
or *
after the item type).
If the field is not optional and does not allow an empty sequence, a
static error
is raised [err:XPST0140].
This rule ensures that finite instances of the type can be constructed.
A record used to represent a node in a binary tree might be represented as:
record(left? as .., value, right? as ..)
A function to walk this tree and enumerate all the values in depth-first order might be written (using XQuery syntax) as:
declare item-type binary-tree as record(left? as .., value, right? as ..); declare function flatten($tree as binary-tree?) as item()* { $tree ! (flatten(?left), ?value, flatten(?right)) }
A record used to represent a node in a tree where each node has an arbitrary number of children might be represented as:
record(value, children as ..*)
A function to walk this tree and enumerate all the values in order might be written (using XQuery syntax) as:
declare item-type tree as record(value, children as ..*); declare function flatten($tree as tree) as item()* { $tree?value, $tree?children ! flatten(.)) }
Note:
If a RecordTest
contains a SelfReference
field that is not optional,
and whose type does not permit an empty sequence, then it will not be possible to construct an instance.
So a RecordTest
such as record(a as ..)
serves no practical
purpose; but it is not disallowed.
Record tests describe a subset of the value space of maps. They do not define any new kinds of values, or any additional operations. They are useful in many cases to describe more accurately the type of a variable, function parameter, or function result, giving benefits both in the readability of the code, and in the ability of the processor to detect and diagnose type errors and to optimize execution.
In particular, if a variable $rec
is known to conform to a particular
record type, then when a lookup expression $rec?field
is used, (a) the processor
can report a type error if $rec
cannot contain an entry with name field
,
and (b) the processor can make static type inferences about the type of value returned by
$rec?field
.
Note:
A number of functions in the standard function library use maps as function arguments;
this is a useful technique where the information to be supplied across the interface is highly
variable. However, the type signature for such functions typically declares the argument type
as map(*)
, which gives very little information (and places very few constraints)
on the values that are actually passed across. Using record tests offers the possibility of
improving this: for example, the options argument of fn:parse-json
, previously
given as map(*)
, can now be expressed as record(liberal? as xs:boolean,
duplicates? as xs:string, escape? as xs:boolean, fallback as function(xs:string) as xs:string, *)
.
In principle the xs:string
type used to describe the duplicates
option could also be replaced by a schema-defined subtype
of xs:string
that enumerates the permitted values ("reject"
,
"use-first"
, "use-last"
).
The use of a record test in the signature of such a function causes the
coercion rules
to be invoked: so, for example, if the function expects an entry in the map to be an xs:double
value, it becomes possible to supply a map in which the corresponding entry has type xs:integer
.
Greater precision in defining the types of such arguments also enables better type checking, better diagnostics, better optimization, better documentation, and better syntax-directed editing tools.
Note:
One of the motivations for introducing record tests is to enable better pattern matching
in XSLT when processing JSON input. With XML input, patterns are often based
around XML element names. JSON has no direct equivalent of XML's element names; matching a JSON object
such as {longitude: 130.2, latitude: 53.4}
relies instead on recognizing the property
names appearing in the object. XSLT 4.0, by integrating record tests into pattern matching syntax,
allows such an object to be matched with a pattern of the form
match="record(longitude, latitude)"
Rules defining whether one record type is a subtype of another are given in 3.7.2.9 Record Tests.
[130] | ArrayTest |
::= |
AnyArrayTest | TypedArrayTest
|
|
[131] | AnyArrayTest |
::= | "array" "(" "*" ")" |
|
[132] | TypedArrayTest |
::= | "array" "(" SequenceType ")" |
The AnyArrayTest
array(*)
matches any
array. The TypedArrayTest
array(X)
matches any array
in which every array member matches the SequenceType
X
.
Examples:
[ 1, 2 ] instance array(*)
returns true()
[] instance of array(xs:string)
returns true()
[ "foo" ] instance of array(xs:string)
returns true()
[ "foo" ] instance of array(xs:integer)
returns false()
[(1,2),(3,4)] instance of array(xs:integer)
returns false()
[(1,2),(3,4)] instance of array(xs:integer+)
returns true()
An array also matches certain other ItemTypes, including:
item()
function(*)
function(xs:integer) as item()*
The function signature of an array
matching array(X)
, treated as a function, is
function(xs:integer) as X
. It is thus always a subtype of
function(xs:integer) as item()*
regardless of the actual member types in the array. The rules for
function coercion mean that any array can be supplied as a value in
a context where the required type has a more specific return type,
such as function(xs:integer) as xs:integer
, even when the array does
not match in the sense required to satisfy the instance of
operator. In such cases, a type error will only occur if an actual
call on the array (treated as a function) returns a value that is
not an instance of the required return type.
Rules defining whether one array type is a subtype of another are given in 3.7.2.8 Arrays.
The type xs:error
has an empty value space; it never appears as a dynamic type or as the content type of a dynamic element or attribute type.
It was defined in XML Schema in the interests of making the type system complete and closed, and it is also available in XPath 4.0
for similar reasons.
Note:
Even though it cannot occur in an instance, xs:error
is a valid type name in a sequence type. The
practical uses of xs:error
as a sequence type are limited, but they do exist. For instance, an error handling function that always raises a dynamic error
never returns a value, so xs:error
is a good choice for the return type of the function.
The semantics of xs:error
are well-defined as a consequence of the fact that xs:error
is defined as a union type with
no member types. For example:
$x instance of xs:error
always returns false, regardless of the value of $x
.
$x cast as xs:error
fails dynamically with error [err:FORG0001]FO31, regardless of the value of $x
.
$x cast as xs:error?
raises a dynamic error
[err:FORG0001]FO31 if exists($x)
, evaluates to the empty sequence if empty($x)
.
xs:error($x)
has the same semantics as $x cast as xs:error?
(see the previous bullet point)
$x castable as xs:error
evaluates to false
, regardless of the value of $x
.
$x treat as xs:error
raises a dynamic error
[err:XPDY0050] if evaluated, regardless of the value of $x
. It never fails statically.
All of the above examples assume that $x
is actually evaluated. If the result of the query does not depend on the value of $x
. the rules specified in 2.4.4 Errors and
Optimization permit an implementation to avoid evaluating $x
and thus to avoid raising an error.
[Definition: Given two sequence types or item types, the rules in this section determine if one is a subtype of the other. If a type A is a subtype of type B, it follows that every value matched by A is also matched by B.]
Note:
The relationship subtype(A, A)
is always true:
every type is a subtype of itself.
Note:
The converse is not necessarily true: we cannot infer that
if every value matched by A is also matched by B, then
A is a subtype of type B. For example, A might be
defined as the set of strings matching the regular expression [A-Z]*
, while B
is the set of strings matching the regular expression [A-Za-z]*
; no subtype
relationship holds between these types.
The rules for deciding whether one sequence type is a subtype of another are given in 3.7.1 Subtypes of Sequence Types. The rules for deciding whether one item type is a subtype of another are given in 3.7.2 Subtypes of Item Types.
Note:
The subtype relationship is not acyclic. There are cases where subtype(A, B)
and
subtype(B, A)
are both true. This implies that A and B
have the same value space, but they can still be different types. For example this applies when A
is a union type with member types xs:string
and xs:integer
, while
B is a union type with member types xs:integer
and xs:string
.
These are different types ("23" cast as A
produces a string, while "23" cast as B
produces an integer, because casting is attempted to each member type in order) but both types have the same value space.
We use the notation A ⊑ B
, or subtype(A, B)
to indicate that
a sequence type
A
is a subtype of a sequence type B
.
This section defines the rules for deciding whether any two sequence types have this relationship.
To define the rules, we divide sequence types into six categories:
The category empty
includes the sequence types empty-sequence()
,
xs:error*
and xs:error?
. All these sequence types
match the empty sequence as their only instance.
The category void
includes the sequence types xs:error
and xs:error+
,
which have no instances (not even the empty sequence).
The categories X?
, X*
, X
and X+
includes all sequence types
having an item type X
other than xs:error
, together with an occurrence indicator of
?
(zero or more), *
(one or more), absent (exactly one), or +
(one or more)
respectively. We use the notation Xi to indicate the item type of such a sequence type.
The judgement A ⊑ B
is then determined by the categories of the two sequence types, as defined
in the table below. In many cases this depends on the relationship between the item types of A
and B
. This is denoted using the notation
Ai ⊆ Bi
,
as defined in 3.7.2 Subtypes of Item Types.
Sequence type B | |||||||
---|---|---|---|---|---|---|---|
empty
|
Bi?
|
Bi*
|
Bi
|
Bi+
|
void
|
||
Sequence type A |
empty
|
true | true | true | false | false | false |
Ai?
|
false |
Ai ⊆ Bi
|
Ai ⊆ Bi
|
false | false | false | |
Ai*
|
false | false |
Ai ⊆ Bi
|
false | false | false | |
Ai
|
false |
Ai ⊆ Bi
|
Ai ⊆ Bi
|
Ai ⊆ Bi
|
Ai ⊆ Bi
|
false | |
Ai+
|
false | false |
Ai ⊆ Bi
|
false |
Ai ⊆ Bi
|
false | |
void
|
true | true | true | true | true | true |
We use the notation A ⊆ B
, or itemtype-subtype(A, B)
to indicate that
an item type
A
is a subtype of an item type B
.
This section defines the rules for deciding whether any two item types have this relationship.
Before applying these rules, any ItemType written
as item-type(N)
is replaced with the definition of the named item type
N
, recursively. The rules are written in terms of the lexical
form of the two item types, but it is
assumed that trivial variations are first
eliminated: comments and unnecessary whitespace are removed, lexical QNames are
replaced by URI-qualified names applying appropriate defaults in the case of unprefixed
names, equivalent forms such as element()
and element(*)
are normalized.
The relationship A ⊆ B
is true
if and only if at least one of the conditions listed in the following subsections applies:
Given item types
A and B,
A
⊆
B is true if any of the following apply:
A is xs:error
.
B is item()
.
A and B are the same item type.
There is an item type
X such that
A ⊆ X
and
X ⊆ B
. (This is referred to below as the transitivity rule).
Note:
The first rule is technically redundant: it is implied by the second rule in 3.7.2.2 Atomic and Union Types.
The type xs:error
is defined as a union type with no member types; therefore it is automatically true that
every member type T satisfies
T ⊆ B
.
Given item types A and B, A
⊆
B is true if any of the following apply:
A and B are generalized atomic types,
and derives-from(A, B)
returns true
.
The derives-from
relationship is defined in 3.5 Sequence Type Matching.
A is a pure union type,
and every type T in the transitive membership of A
satisfies
T ⊆ B
.
union(xs:short, xs:long) ⊆ xs:integer
because xs:short ⊆ xs:integer
and xs:long ⊆ xs:integer
.
union(P, Q) ⊆ union(P, Q, R)
because P ⊆ union(P, Q, R)
and Q ⊆ union(P, Q, R)
.
Note:
This rule applies both when A
is a schema-defined union type
and when it is a LocalUnionType.
A is an EnumerationType, and B matches every string literal in the enumeration of A.
Given item types A and B, A
⊆
B is true if any of the following apply:
A is a KindTest and B is node()
.
A is processing-instruction(N)
for any name N,
and B is processing-instruction()
.
A is document-node(E)
for any ElementTest
E,
and B is document-node()
.
All the following are true:
A is document-node(Ae)
B is document-node(Be)
Ae ⊆ Be
[Definition: In these rules, if M and N are NameTests, then M wildcard-matches N is true if every name that matches M also matches N.] More specifically, this is the case if any of the following apply:
M and N are the same NameTest
.
M is an EQName
and N is a
Wildcard that matches M.
N is the Wildcard
*
.
Given item types A and B, A
⊆
B is true if any of the following apply.
A is an ElementTest and
B is either element()
or element(*)
All the following are true:
A is either element(An)
or element(An, T)
or element(An, T?)
for any type T
B is either element(Bn)
or element(Bn, xs:anyType?)
An wildcard-matches Bn
element(title) ⊆ element(*)
element(title, xs:string) ⊆ element(*)
element(title, xs:string?) ⊆ element(*)
element(title) ⊆ element(title, xs:anyType?)
element(title, xs:integer) ⊆ element(title, xs:anyType?)
element(title, xs:string?) ⊆ element(title, xs:anyType?)
element(my:title) ⊆ element(*:title)
element(my:title) ⊆ element(my:*)
All the following are true:
A is element(An, At)
B is element(Bn, Bt)
An wildcard-matches Bn
derives-from(At, Bt)
.
All the following are true:
A is either element(An, At)
or
element(An, At?)
B is element(Bn, Bt?)
An wildcard-matches Bn
derives-from(At, Bt)
.
All the following are true:
A is schema-element(An)
B is schema-element(Bn)
Every element declaration that is an actual member of the substitution group of An is also an actual member of the substitution group of Bn.
Note:
The fact that P is a member of the substitution group of Q does not mean that every element declaration in the substitution group of P is also in the substitution group of Q. For example, Q might block substitution of elements whose type is derived by extension, while P does not.
Given item types A and B, A
⊆
B is true if any of the following apply:
A is an AttributeTest and
B is either attribute()
or attribute(*)
All the following are true:
A is either attribute(An)
or
attribute(An, T)
for any type T.
B is either attribute(Bn)
or
attribute(Bn, xs:anyAtomicType)
An wildcard-matches Bn
All the following are true:
A is attribute(An, At)
B is attribute(Bn, Bt)
An wildcard-matches Bn
derives-from(At, Bt)
.
attribute(*, xs:ID) ⊆ attribute(*, xs:string)
attribute(my:*, xs:ID) ⊆ attribute(*, xs:string)
attribute(code, xs:ID) ⊆ attribute(code, xs:string)
attribute(code, xs:ID) ⊆ attribute(*, xs:string)
attribute(code, xs:ID) ⊆ attribute(*:code, xs:ID)
attribute(my:code, xs:ID) ⊆ attribute(my:*, xs:string)
All the following are true:
A is schema-attribute(An)
B is schema-attribute(Bn)
the expanded QName of An equals the expanded QName of Bn
Given item types A and B, A
⊆
B is true if any of the following apply:
All the following are true:
A is a FunctionTest
B is
function(*)
All the following are true:
A is
function(a1, a2, ... aM) as RA
B is
function(b1, b2, ... bN) as RB
N (the arity of B) equals M (the arity of A)
RA ⊑ RB
For all values of p between 1 and N,
bp ⊑ ap
function(xs:integer) as xs:string ⊆ function(xs:long) as xs:string
function(xs:integer) as xs:ID ⊆ function(xs:integer) as xs:string
function(xs:integer) as xs:ID ⊆ function(xs:long) as xs:string
Note:
Function return types are covariant because this rule requires
RA ⊑ RB
for return types.
Function parameter types are contravariant because this rule requires
bp ⊑ ap
for parameter types.
Given item types A and B, A
⊆
B is true if any of the following apply:
Both of the following are true:
A is map(K, V)
,
for any K and V
B is map(*)
All the following are true:
A is map(Ka, Va)
B is map(Kb, Vb)
Ka ⊆ Kb
Va ⊑ Vb
Both the following are true:
A is map(*)
(or, because of the transitivity rules, any other map type)
B is function(*)
Both the following are true:
A is map(*)
(or, because of the transitivity rules, any other map type)
B is
function(xs:anyAtomicType) as item()*
Both the following are true:
A is map(K, V)
B is function(xs:anyAtomicType) as W
,
where W has the same item type as V, but also allows
an empty sequence.
map(xs:int, node()) ⊆ function(xs:anyAtomicType) as node()?
map(xs:int, node()+) ⊆ function(xs:anyAtomicType) as node()*
The function accepts type xs:anyAtomicType
rather than xs:int
,
because $M("xyz")
is a valid call on a map (treated as a function) even
when all the keys in the map are integers.
The return type of the function is extended from node()
or node()+
to allow an empty sequence
because $M("xyz")
can return an empty sequence even if none of the entries
in the map contains an empty sequence.
Given item types A and B, A
⊆
B is true if any of the following apply:
Both the following are true:
A is array(X)
B is array(*)
All the following are true:
A is array(X)
B is array(Y)
X ⊑ Y
Both the following are true:
A is array(*)
(or, because of the transitivity rules, any other array type)
B is function(*)
Both the following are true:
A is array(*)
(or, because of the transitivity rules, any other array type)
B is function(xs:integer) as item()*
Both the following are true:
A is array(X)
B is function(xs:integer) as X
Given item types A and B, A
⊆
B is true if any of the following apply:
All of the following are true:
A is a record test
B is map(*)
All of the following are true:
A is a non-extensible record test
B is map(K, V)
K is either xs:string
or xs:anyAtomicType
For every field F in A,
where T is the declared type of F (or its default, item()*
),
T ⊑ V
.
All of the following are true:
A is a non-extensible record test.
B is a non-extensible record test.
Every field in A is also declared in B.
Every mandatory field in B is also declared in A.
For every field that is declared in both A and B,
where the declared type in A is T
and the declared type in B is U,
T ⊑ U
.
All of the following are true:
A is an extensible record test
B is an extensible record test
Every mandatory field in B is also declared in A.
For every field that is declared in both A and B,
where the declared type in A is T
and the declared type in B is U,
T ⊑ U
.
For every field that is declared in B
but not in A, the declared type in B is item()*
.
All of the following are true:
A is a non-extensible record test.
B is an extensible record test.
Every mandatory field in B is also declared in A.
Every field that is declared in B with a type other than item()*
is also declared in A.
For every field that is declared in both A and B,
where the declared type in A is T
and the declared type in B is U,
T ⊑ U
.