This section discusses each of the basic kinds of expression. Each kind of expression has a name such as PathExpr
, which is introduced on the left side of the grammar production that defines the expression. Since XPath 4.0 is a composable language, each kind of expression is defined in terms of other expressions whose operators have a higher precedence. In this way, the precedence of operators is represented explicitly in the grammar.
The order in which expressions are discussed in this document does not reflect the order of operator precedence. In general, this document introduces the simplest kinds of expressions first, followed by more complex expressions. For the complete grammar, see Appendix [A XPath 4.0 Grammar].
The highest-level symbol in the XPath grammar is XPath.
[1] | XPath |
::= |
Expr
|
|
[10] | Expr |
::= |
ExprSingle ("," ExprSingle)* |
|
[11] | ExprSingle |
::= |
WithExpr
|
The XPath 4.0 operator that has lowest precedence is the comma operator, which is used to combine two operands to form a sequence. As shown in the grammar, a general expression (Expr) can consist of multiple ExprSingle operands, separated by commas. The name ExprSingle denotes an expression that does not contain a top-level comma operator (despite its name, an ExprSingle may evaluate to a sequence containing more than one item.)
The symbol ExprSingle is used in various places in the grammar where an expression is not allowed to contain a top-level comma. For example, each of the arguments of a function call must be an ExprSingle, because commas are used to separate the arguments of a function call.
After the comma, the expressions that have next lowest precedence are ForExpr, LetExpr, QuantifiedExpr, IfExpr, and OrExpr. Each of these expressions is described in a separate section of this document.
[12] | WithExpr |
::= | "with" NamespaceDeclaration ("," NamespaceDeclaration)* EnclosedExpr
|
|
[13] | NamespaceDeclaration |
::= |
QName "=" StringLiteral
|
|
[9] | EnclosedExpr |
::= | "{" Expr? "}" |
The namespace context for an expression can be set using a construct of the form:
with xmlns="http://example.com/, xmlns:a="http://example.com/a" { /doc/a:element/b }
The static context for the enclosed expression will be the same as the static context for the WithExpr itself, except for modifications defined below.
The QName
used in a NamespaceDeclaration
must be either xmlns
or xmlns:prefix
where prefix
is some
NCName
.
If more than one NamespaceDeclaration specifies
the same QName
, all but the last of the duplicates are ignored.
If the QName is "xmlns"
then:
If the StringLiteral
is a zero-length string:
The default element namespace is set to absent, meaning that unprefixed element names are treated as being in no namespace.
Any binding for the zero-length prefix in the statically known namespaces is removed.
If the StringLiteral
is not zero-length:
The default element namespace is set to the supplied namespace URI, meaning that unprefixed element names are treated as being in that namespace.
A binding that maps the zero-length prefix to the specified namespace URI is added to the statically known namespaces.
If the QName is in the form xmlns:prefix
then the StringLiteral
must not be zero-length; the effect is that a binding that maps the given prefix
to
the specified namespace URI is added to the statically known namespaces.
For example, the expression:
with xmlns="http://www.acme.com/" {a/b[c=3]}
is equivalent to the expression:
Q{http://www.acme.com/}a/Q{http://www.acme.com/}b[Q{http://www.acme.com/}c=3]
[144] | Comment |
::= | "(:" (CommentContents | Comment)* ":)" |
/* ws: explicit */ |
/* gn: comments */ | ||||
[149] | CommentContents |
::= | (Char+ - (Char* ('(:' | ':)') Char*)) |
Comments may be used to provide information relevant to programmers who read an expression. Comments are lexical constructs only, and do not affect expression processing.
Comments are strings, delimited by the symbols (:
and :)
. Comments may be nested.
A comment may be used anywhere ignorable whitespace is allowed (see A.2.4.1 Default Whitespace Handling).
The following is an example of a comment:
(: Houston, we have a problem :)
[Definition: Primary expressions are the basic primitives of the language. They include literals, variable references, context item expressions, and function calls. A primary expression may also be created by enclosing any expression in parentheses, which is sometimes helpful in controlling the precedence of operators.] Map and Array Constructors are described in 4.14 Maps and Arrays.
[72] | PrimaryExpr |
::= |
Literal
|
|
[82] | FunctionItemExpr |
::= |
NamedFunctionRef | InlineFunctionExpr
|
[Definition: A literal is a direct syntactic representation of an atomic value.] XPath 4.0 supports two kinds of literals: numeric literals and string literals.
[73] | Literal |
::= |
NumericLiteral | StringLiteral
|
|
[74] | NumericLiteral |
::= |
IntegerLiteral | DecimalLiteral | DoubleLiteral
|
|
[136] | IntegerLiteral |
::= |
Digits
|
|
[137] | DecimalLiteral |
::= | ("." Digits) | (Digits "." [0-9]*) |
/* ws: explicit */ |
[138] | DoubleLiteral |
::= | (("." Digits) | (Digits ("." [0-9]*)?)) [eE] [+-]? Digits
|
/* ws: explicit */ |
[139] | StringLiteral |
::= | ('"' (EscapeQuot | [^"])* '"') | ("'" (EscapeApos | [^'])* "'") |
/* ws: explicit */ |
[142] | EscapeQuot |
::= | '""' |
|
[143] | EscapeApos |
::= | "''" |
|
[148] | Digits |
::= | [0-9]+ |
The value of a numeric literal containing no ".
" and no e
or E
character is an atomic value of type xs:integer
. The value of a numeric literal containing ".
" but no e
or E
character is an atomic value of type xs:decimal
. The value of a numeric literal containing an e
or E
character is an atomic value of type xs:double
. The value of the numeric literal is determined by casting it to the
appropriate type according to the rules for casting from xs:untypedAtomic
to a numeric type as specified in Section
19.2 Casting from xs:string and xs:untypedAtomic
FO31.
Note:
The effect of the above rule is that in the case of an integer or decimal literal, a dynamic error [err:FOAR0002]FO31 will generally be raised if the literal is outside the range of values supported by the implementation (other options are available: see Section 4.2 Arithmetic operators on numeric values FO31 for details.)
The XML Schema specification allows implementations to impose a limit (which
must not be less than 18 digits) on the size of integer and decimal
values. The full range of values of built-in subtypes of xs:integer
,
such as xs:long
and xs:unsignedLong
, can be supported only if the
limit is 20 digits or higher. Negative numbers such as the minimum
value of xs:long
(-9223372036854775808
) are technically unary
expressions rather than literals, but implementations may prefer to
ensure that they are expressible.
The value of a string literal is an atomic value whose type is xs:string
and whose value is the string denoted by the characters between the
delimiting apostrophes or quotation marks. If the literal is delimited by apostrophes, two adjacent apostrophes within the literal are interpreted as a single apostrophe. Similarly, if the literal is delimited by quotation marks, two adjacent quotation marks within the literal are interpreted as one quotation mark.
Here are some examples of literal expressions:
"12.5"
denotes the string containing the characters '1', '2', '.', and
'5'.
12
denotes the xs:integer
value twelve.
12.5
denotes the xs:decimal
value twelve and one half.
125E2
denotes the xs:double
value twelve thousand, five hundred.
"He said, ""I don't like it."""
denotes a string containing two quotation marks and one apostrophe.
Note:
When XPath expressions are embedded in contexts where quotation marks have special significance, such as inside XML attributes, additional escaping may be needed.
The xs:boolean
values true
and false
can be constructed by calls to the
built-in functions
fn:true()
and fn:false()
, respectively.
Values of other simple types can be constructed by calling the constructor function for the given type. The constructor functions for XML Schema built-in types are defined in Section 18.1 Constructor functions for XML Schema built-in atomic types FO31. In general, the name of a constructor function for a given type is the same as the name of the type (including its namespace). For example:
xs:integer("12")
returns the integer value twelve.
xs:date("2001-08-25")
returns an item whose type is xs:date
and whose value represents the date 25th August 2001.
xs:dayTimeDuration("PT5H")
returns an item whose type is xs:dayTimeDuration
and whose value represents a duration of five hours.
Constructor functions can also be used to create special values that have no literal representation, as in the following examples:
xs:float("NaN")
returns the special floating-point value, "Not a Number."
xs:double("INF")
returns the special double-precision value, "positive infinity."
Constructor functions are available for all simple types,
including union types. For example, if my:dt
is a user-defined union
type whose member types are xs:date
, xs:time
, and xs:dateTime
, then
the expression my:dt("2011-01-10")
creates an atomic value of type
xs:date
. The rules follow XML Schema validation rules for union types:
the effect is to choose the first member type that accepts the given
string in its lexical space.
It is also possible to construct values of various types by using a cast
expression. For example:
9 cast as
hatsize
returns the atomic value 9
whose type is hatsize
.
[75] | VarRef |
::= | "$" VarName
|
|
[76] | VarName |
::= |
EQName
|
[Definition: A variable reference is an EQName preceded by a $-sign.]
An unprefixed variable reference is in no namespace. Two variable references are equivalent if their expanded QNames are equal (as defined by the eq
operator). The scope of a variable binding is defined separately for each kind of
expression that can bind variables.
Every variable reference must match a name in the in-scope variables.
Every variable binding has a static scope. The scope defines where references to the variable can validly occur. It is a static error [err:XPST0008] to reference a variable that is not in scope. If a variable is bound in the static context for an expression, that variable is in scope for the entire expression except where it is occluded by another binding that uses the same name within that scope.
At evaluation time, the value of a variable reference is the value to which the relevant variable is bound.
[77] | ParenthesizedExpr |
::= | "(" Expr? ")" |
Parentheses may be used to override the precedence rules.
For example, the expression (2 + 4)
* 5
evaluates to thirty, since the parenthesized expression (2 + 4)
is evaluated first and its result is multiplied by five. Without
parentheses, the expression 2 + 4 * 5
evaluates to twenty-two, because the multiplication operator has higher
precedence than the addition operator.
Empty parentheses are used to denote an empty sequence, as described in 4.7.1 Sequence Concatenation.
[78] | ContextItemExpr |
::= | "." |
A context item expression evaluates to
the context item, which may be either a node (as in the
expression
fn:doc("bib.xml")/books/book[fn:count(./author)>1]
),
or an atomic value or function (as in the expression (1 to
100)[. mod 5 eq 0]
).
If the context item is absentDM31, a context item expression raises a dynamic error [err:XPDY0002].
[9] | EnclosedExpr |
::= | "{" Expr? "}" |
[Definition: An enclosed expression is an instance of the EnclosedExpr production, which allows an optional expression within curly braces.]
[Definition: In an enclosed expression, the optional expression enclosed in curly braces is called the content expression.] If the content expression is not provided explicitly, the content expression is ()
.
Note:
Despite the name, an enclosed expression is not actually an expression in its own right; rather it is a construct that is used in the grammar of many other expressions.
Functions in XPath 4.0 arise in two ways:
A function definition contains information about a family of functions with the same name and a defined arity range. These functions are in most cases known statically (they appear in the statically known function definitions), but there may be further function definitions that are known only dynamically (appearing in the dynamically known function definitions).
Function items are XDM items that can be called using a dynamic function call. They are values that can be bound to variables, passed as arguments, returned as function results, and generally manipulated in the same way as other XDM values.
The functions defined by a statically known function definition can be invoked using a
static function call. Function items corresponding
to these definitions can also be obtained, as dynamic values, by evaluating a named function reference.
Function items can also be obtained using the fn:function-lookup
function: in this case the function name and arity do not need to be known statically, and the function definition
need not be present in the static context, so long as it is in the dynamic context.
The mechanisms for making function calls by reference to function definitions and function items are described in the following sections.
The static context for an expression includes a set of statically known function definitions. Every function definition in the static context has a name (which is an expanded QName) and an arity range, which is a range of permitted arities for calls on that function. Two function definitions having the same name must not have overlapping arity ranges. This means that for a given static function call, it is possible to identify the target function definition in the static context unambiguously from knowledge of the function name and the number of supplied arguments.
A static function call is bound to a function definition in the static context by matching the name and arity. If the function call has P positional arguments followed by K keyword arguments, then the required arity is P+K, and the static context must include a function definition whose name matches the expanded QName in the function call, and whose arity range includes this required arity. This is the function chosen to be called. The result of the function is obtained by evaluating the expression that forms its implementation, with a dynamic context that provides values for all the declared parameters, initialized as described in 4.4.1.2 Evaluating Static Function Calls below.
Similarly, a function reference of the form f#N
binds to a function in the
static context whose name matches f where MinP ≤ N and MaxP ≥ N
.
The result of evaluating a function reference is a (dynamic) function which can be called
using a dynamic function call. Dynamic functions are never variadic and their arguments
are always supplied positionally. For example, the function reference fn:concat#3
returns a function with arity 3, which is always called by supplying three positional
arguments, and whose effect is the same as a static call on fn:concat
with
three positional arguments.
The detailed rules for evaluating static function calls and function references are defined in subsequent sections.
[79] | FunctionCall |
::= |
EQName
ArgumentList
|
/* xgc: reserved-function-names */ |
/* gn: parens */ | ||||
[61] | ArgumentList |
::= | "(" ((PositionalArguments ("," KeywordArguments)?) | KeywordArguments)? ")" |
|
[63] | PositionalArguments |
::= |
Argument ("," Argument)* |
|
[80] | Argument |
::= |
ExprSingle | ArgumentPlaceholder
|
|
[81] | ArgumentPlaceholder |
::= | "?" |
|
[64] | KeywordArguments |
::= |
KeywordArgument ("," KeywordArgument)* |
|
[65] | KeywordArgument |
::= |
EQName ":=" Argument
|
[Definition: A static function call consists of an EQName followed by a parenthesized list of zero or more arguments.]
The argument list consists of zero or more positional arguments, followed by zero or more keyword arguments.
[Definition: An argument to a function call is either an
argument expression or an ArgumentPlaceholder
(?
); in both cases it may
either be supplied positionally, or identified by a name (called a keyword).]
This section is concerned with static function calls in which none of the arguments are ArgumentPlaceholders. Calls using one or more ArgumentPlaceholders are covered in the section 4.4.2.2 Partial Function Application.
If the function name supplied in a static function call is an unprefixed lexical QName, it is expanded using the default function namespace in the static context.
The expanded QName used as the function name, and the number of arguments in the static function call (the required arity) must match the name and arity range of a function definition in the static context using the rules defined in the previous section; if there is no match, a static error is raised [err:XPST0017].
Evaluation of static function calls is described in 4.4.1.2 Evaluating Static Function Calls .
Since the arguments of a function call are separated by commas, any argument expression that contains a top-level comma operator must be enclosed in parentheses. Here are some illustrative examples of static function calls:
my:three-argument-function(1, 2, 3)
denotes a static function call with three
positional arguments. The
corresponding function declaration must define at least three parameters, and may define
more, provided they are optional.
my:two-argument-function((1,2), 3)
denotes a static function call with two arguments, the first of which is a
sequence of two values. The
corresponding function declaration must define at least two parameters, and may define
more, provided they are optional.
my:two-argument-function(1, ())
denotes a static function call with two arguments,
the second of which is an empty sequence.
my:one-argument-function((1, 2,
3))
denotes a static function call with one argument that is a sequence of three
values.
my:one-argument-function(( ))
denotes a static function call with one argument that is an empty sequence.
my:zero-argument-function( )
denotes a static function call with zero arguments.
fn:lang(node:=$n, language:='de')
is a static function
call with two keyword arguments. The corresponding function declaration defines two parameters,
a required parameter language
and an optional parameter node
.
This call supplies values for both parameters. It is equivalent to the call
fn:lang('de', $n)
. Note that the keyword arguments are in a different
order from the parameter declarations.
fn:sort(//employee, key := ->{xs:decimal(salary)})
is a static function
call with one positional argument and one keyword argument.
The corresponding function declaration defines three parameters,
a required parameter $input
, an optional parameter $collation
,
and an optional parameter $key
This call supplies values for the first and third parameters, leaving the second parameter ($collation
)
to take its default value. The default value of the $collation
parameter
is given as fn:default-collation()
, so the value supplied to the function is the
default collation from the dynamic context of the caller. It is equivalent to the call
fn:sort(//employee, fn:default-collation(), ->{xs:decimal(salary)})
.
An EQName
in a KeywordArgument
is expanded to a QName value; if there
is no prefix, then the name is in no namespace (otherwise the prefix is resolved in the usual way).
The keywords used in a function call (after expansion to QNames) must be distinct
[err:XPST0141]; [err:XPST0142].
This section applies to static function calls where none of the
arguments is an ArgumentPlaceholder
. For function calls involving
placeholders, see 4.4.2.2 Partial Function Application.
When a static function call FC is evaluated with respect to a static context SC and a dynamic context DC, the result is obtained as follows:
The function definition FD to be used is found in >the statically known function definitions of SC.
The required arity is the total number of arguments in the function call, including both positional and keyword arguments.
There can be at most one function definition
FD in the
statically known function definitions component of SC whose function name
matches the expanded QName in FC and whose arity range
includes the arity of FC's ArgumentList
.
If there is no such function definition, a static error [err:XPST0017] is raised.
Each parameter in the function definition FD is matched to an argument expression as follows:
If there are N positional arguments in the function call, the corresponding argument expressions are matched pairwise to the first N parameters in the declaration. For this purpose the required parameters and optional parameters in FD are concatenated into a single list, in order.
Any keyword arguments in FC are then matched to parameters (whether required or optional) in FD by comparing the keyword used in FC with the paramater name declared in FD. Each keyword must match the name of a declared parameter [err:XPST0142], and this must be one that has not already been matched to a positional argument. [err:XPST0141].
If any required parameter has not been matched to any argument in FC by applying the above rules, a static error is reported [err:XPST0141]
If any optional parameter has not been matched to any argument in FC by applying the above rules, then the parameter is matched to the default value expression for that parameter in FD.
Each argument expression established by the above rules is evaluated with respect to DC. The order of argument evaluation is implementation dependent and it is not required that an argument be evaluated if the function body can be evaluated without evaluating that argument.
Note:
All argument expressions, including default value expressions, are evaluated in the dynamic
context of the function call. It is therefore possible to use a default value expression such as
.
, or /
, or fn:current-dateTime()
, whose value depends on the
dynamic context of the function call.
If the expression used for the default value of a parameter has no dependencies on the dynamic context, then an implementation may choose to reuse the same value on repeated function calls rather than re-evaluating it on each function call.
Note:
This is relevant, for example, if the expression constructs new nodes.
The result of evaluating the argument expression is converted to the required type (the
declared type associated with the corresponding parameter in the function declaration, defaulting
to item()*
) by applying the coercion rules.
The result of the function call is obtained as follows:
FD's implementation is invoked in an implementation-dependent way. The processor makes the following information available to that invocation:
The converted argument values;
An empty set of nonlocal variable bindings; and
A static context and dynamic context. If FD's implementation is associated with a static and a dynamic context, then these are supplied, otherwise SC and DC are supplied.
How this information is used is implementation-defined. An API used to call external functions must state how the static and dynamic contexts are provided to a function that is called. The F&O specification states how the static and dynamic contexts are used in each function that it defines. A host language must state how the static and dynamic contexts are used in functions that it provides.
The result is converted to the required type (the
declared return type in the function declaration, defaulting
to item()*
) by applying the coercion rules.
The result of applying the coercion rules is either an instance of FD's return type or a dynamic error. This result is then the result of evaluating FC.
Note:
A host language may define alternative rules for processing the result, especially in the case of external functions implemented using a non-XDM type system.
Errors raised by built-in functions are defined in [XQuery and XPath Functions and Operators 4.0].
Errors raised by host-language-dependent functions are implementation-defined.
The following function call uses the function
Section
2.5 fn:base-uri
FO31. Use of SC
and DC
and errors raised by this function are all defined in
[XQuery and XPath Functions and Operators 4.0].
fn:base-uri()
A function item is an XDM value that can be bound to a variable, or manipulated in various ways by XPath 4.0 expressions. The most significant such expression is a dynamic function call, which supplies values of arguments and evaluates the function to produce a result.
The syntax of dynamic function calls is defined in 4.5.2 Dynamic Function Calls.
A number of constructs can be used to produce a function item, notably:
A named function reference (see 4.4.2.3 Named Function References)
constructs a function item by reference to function definitions
in the static context: for example fn:node-name#1
returns a function whose effect is to call the static fn:node-name
function
with one argument.
An inline function (see 4.4.2.4 Inline Function Expressions)
constructs a function whose implementation is defined locally. For example the
construct ->($x){$x+1}
returns a function whose effect is to increment
the value of the supplied argument.
A partial function application (see
4.4.2.2 Partial Function Application) derives one function from another by supplying
the values of some of its arguments. For example, fn:ends-with(?, ".txt")
returns
a function with one argument that tests whether the supplied string ends with the substring
".txt"
.
Maps and arrays are also functions. See 4.14.1.1 Map Constructors and 4.14.2.1 Array Constructors.
The fn:function-lookup
function can be called to discover functions
that are present in the dynamic context.
The fn:load-xquery-module
function can be called to load functions
dynamically from an external XQuery library module.
Some built-in functions such as fn:random-number-generator
and fn:op
return a function item as their result.
These constructs are described in detail in the following sections, or in [XQuery and XPath Functions and Operators 4.0].
This section applies to dynamic function calls whose arguments do not include
an ArgumentPlaceholder
. For function calls that include a placeholder,
see 4.4.2.2 Partial Function Application.
[Definition: A dynamic function call is an expression that is evaluated by calling a function item, which is typically obtained dynamically.]
When a dynamic function call FC is evaluated, the result is obtained as follows:
The function item
F to be called
is obtained by evaluating the base expression of the function call.
If this yields a sequence consisting of a single function
whose arity matches the number of arguments in the ArgumentList
,
let F denote that function.
Otherwise, a type error is raised
[err:XPTY0004].
Note:
Keyword arguments are not allowed in a dynamic function call.
Argument expressions are evaluated, producing argument values. The order of argument evaluation is implementation-dependent and an argument need not be evaluated if the function body can be evaluated without evaluating that argument.
Each argument value is converted to the corresponding parameter type in F's signature by applying the coercion rules, resulting in a converted argument value .
If F is a map, it is evaluated as described in 4.14.1.2 Map Lookup using Function Call Syntax.
If F is an array, it is evaluated as described in 4.14.2.2 Array Lookup using Function Call Syntax.
If F's implementation is an XPath 4.0 expression (for example, if F is an anonymous function, or a partial application of such a function):
F's implementation
is evaluated.
The static context for this evaluation
is the static context of the XPath 4.0 expression.
The dynamic context for this evaluation is obtained
by taking the dynamic context of the
InlineFunctionExpr
that contains the FunctionBody
, and
making the following changes:
The focus (context item, context position, and context size) is absentDM31.
In the variable values component of the dynamic context, each converted argument value is bound to the corresponding parameter name.
When this is done,
the converted argument values retain
their dynamic types,
even where these are subtypes
of the declared parameter types.
For example, a function with
a parameter $p
of type xs:decimal
can be called with an argument of type xs:integer
,
which is derived from xs:decimal
.
During the processing of this function
call, the value of $p
inside the body of the function
retains its dynamic type of xs:integer
.
F's nonlocal variable bindings are also added to the variable values. (Note that the names of the nonlocal variables are by definition disjoint from the parameter names, so there can be no conflict.)
The value returned by evaluating the function body is then converted to the declared return type of F by applying the coercion rules. The result is then the result of evaluating FC.
As with argument values,
the value returned by a function
retains its dynamic type,
which may be a subtype of the declared return type of F.
For example, a function that has
a declared return type of xs:decimal
may in fact return a value of dynamic type xs:integer
.
$incr
is a nonlocal variable that is available within the function because its variable binding has been added to the variable values of the function.. Even though the parameter and return type of this function are both xs:decimal
,
the more specific type xs:integer
is preserved in both cases.
let $incr := 1, $f := function ($i as xs:decimal) as xs:decimal { $i + $incr } return $f(5)
The following example will raise a dynamic error [err:XPDY0002]:
let $vat := function() { @vat + @price } return shop/article/$vat()
Instead, the context item can be used as an argument to the anonymous function:
let $vat := function($art) { $art/@vat + $art/@price } return shop/article/$vat(.)
Or, the value can be referenced as a nonlocal variable binding:
let $ctx := shop/article, $vat := function() { for $a in $ctx return $a/@vat + $a/@price } return $vat()
If F's implementation is not an XPath 4.0 expression (e.g., F is a built-in function the implementation of the function is evaluated, and the result is converted to the declared return type, in the same way as for a static function call (see 4.4.1.1 Static Function Call Syntax).
Errors may be raised in the same way.
[Definition: A static or dynamic function call is a partial function application if one or more arguments is an ArgumentPlaceholder.]
The result of a partial function application is a function item, whose arity is equal to the number of placeholders in the call.
The result is obtained as follows:
The function F to be partially applied is determined in the same way as for a
(static or dynamic) function call without placeholders, as described in the preceding sections.
For this purpose an ArgumentPlaceholder
contributes to the count of
arguments.
Arguments other than placeholders are evaluated, mapped to corresponding parameters in the function signature of F, and converted to the required type of the parameter, using the rules for static and dynamic function calls as appropriate. In the case of static function calls, this includes optional parameters for which no argument expression or placeholder is supplied in the call.
The result of the partial function application is a new function, which is a partially applied function.
[Definition: A partially applied function
is a function created by partial function application.]
[Definition: In a partial function application, a supplied parameter
is any parameter other than one for which the ArgumentList
includes
a placeholder.]
A partial function application need not have any supplied parameters. A partially applied function has
the following properties (which are defined in Section
2.8.1 Functions
DM31):
name: Absent.
parameter names: The parameter names of F, removing the names of supplied parameters. (So the function's arity is the arity of F minus the number of fixed positions.)
signature: The signature of F, removing the types of supplied parameters. An implementation which can determine a more specific signature (for example, through use of type analysis) is permitted to do so.
implementation: The implementation of F. If this is not an XPath 4.0 expression then the new function's implementation is associated with a static context and a dynamic context in one of two ways: if F's implementation is already associated with contexts, then those are used; otherwise, SC and DC are used.
nonlocal variable bindings: The nonlocal variable bindings of F, plus, for each supplied parameter, a binding of the converted argument value to the corresponding parameter name.
In the following example, $f
is an anonymous function, and $paf
is a partially applied function created from $f
.
let $f := function ($seq, $delim) { fn:fold-left($seq, "", fn:concat(?, $delim, ?)) }, $paf := $f(?, ".") return $paf(1 to 5)
$paf
is also an anonymous function. It has one parameter, named $delim
, which is taken from the corresponding parameter in $f
(the other parameter is fixed). The implementation of $paf
is the implementation of $f
, which is fn:fold-left($seq, "", fn:concat(?, $delim, ?))
. This implementation is associated with the SC
and DC
of the original expression in $f
. The nonlocal bindings associate the value "."
with the parameter $delim
.
The following partial function application creates a function that computes the sum of squares of a sequence.
let $sum-of-squares := fn:fold-right(?, 0, function($a, $b) { $a*$a + $b }) return $sum-of-squares(1 to 3)
$sum-of-squares
is an anonymous function. It has one parameter, named $seq
, which is taken from the corresponding parameter in fn:fold-right
(the other two parameters are fixed). The implementation is the implementation of fn:fold-right
, which is a built-in context-independent function. The nonlocal bindings contain the fixed bindings for the second and third parameters of fn:fold-right
.
Partial function application never returns a map or an array. If $F
is a map or an array, then $F(?)
is
a partial function application that returns a function, but the function it returns is not a map nor an array.
[83] | NamedFunctionRef |
::= |
EQName "#" IntegerLiteral
|
/* xgc: reserved-function-names */ |
[135] | EQName |
::= |
QName | URIQualifiedName
|
[Definition:
A named function reference is an expression (written name#arity
)
which evaluates to a function item.]
The name and arity of the required function are known statically.
If the EQName is a lexical QName, it is expanded using the default function namespace in the static context.
The expanded QName and arity must correspond to a function definition
present in the static context.
More specifically, for a named function reference F#N
,
there must be a function definition in the statically known function definitions
whose name matches F, and whose arity range includes N
.
Call this function definition
FD.
If the function is context dependent, then the returned function is associated with the static context of the named function reference and the dynamic context in which the named function reference is evaluated.
Consider:
let $f := <foo/>/fn:name#0 return <bar>/$f()
The function fn:name()
, with no arguments, returns the name of the context node. The function
item delivered by evaluating the expression fn:name#0
returns the name of the element that was the
context node at the point where the function reference was evaluated (that is, the <foo>
element).
This expression therefore returns "foo", not "bar".
If the expanded QName and arity in a named function reference do not match the name and arity range of a function definition in the static context, a static error is raised [err:XPST0017].
The value of a NamedFunctionRef
is a function item
FI
obtained from FD
as follows:
The name of FI is the name of FD.
The parameter names of FI are the first A parameter names of FD, where A is the required arity.
The signature of FI is formed from the required types of the first A parameters of FD, and the function result type of FD.
The implementation of FI is the implementation of FD.
The nonlocal variable bindings of FI comprise bindings of the names of parameters of FD beyond the A'th parameter, to their respective default values. The evaluation of the expressions that define these default values occurs in the dynamic context of the named function reference.
Note:
Consider the built-in function fn:format-date
which has an arity range of 2 to 5. The named function reference fn:format-date#3
returns a function item whose three parameters correspond to the first three parameters
of fn:format-date
; the remaining two arguments will take their default values.
To obtain an arity-3 function that binds to arguments 1, 2, and 5 of fn:format-date
,
use the partial function application format-date(?, ?, place:?)
.
Furthermore, if the function returned by the evaluation of
a NamedFunctionRef
has an
implementation-dependent implementation, then the
implementation of this function is associated with the
static context of this NamedFunctionRef
expression and with the dynamic context in which
the NamedFunctionRef
is evaluated.
The following are examples of named function references:
fn:abs#1
references the fn:abs
function which takes a single argument.
fn:concat#5
references the fn:concat
function which takes 5 arguments.
local:myfunc#2
references a function named local:myfunc
which takes 2 arguments.
Note:
Function items, as values in the data model, have a fixed arity, and
a dynamic function call always supplies the arguments positionally. Although the base function
referred to may be variadic, the result of evaluating the function reference is a function that
has fixed arity. In effect, the result of evaluating my:func#3
is the
same as the result of evaluating the inline function expression function($x, $y, $z){my:func($x, $y, $z)}
,
except that the returned function has a name (it retains the name my:func
).
[84] | InlineFunctionExpr |
::= | (("function" FunctionSignature) | ("->" FunctionSignature?)) FunctionBody
|
|
[3] | FunctionSignature |
::= | "(" ParamList? ")" TypeDeclaration? |
|
[6] | ParamList |
::= |
Param ("," Param)* |
|
[7] | Param |
::= | "$" EQName
TypeDeclaration? |
|
[94] | TypeDeclaration |
::= | "as" SequenceType
|
|
[8] | FunctionBody |
::= |
EnclosedExpr
|
[Definition: An inline function expression creates an anonymous function defined directly in the inline function expression.] An inline function expression specifies the names and SequenceTypes of the parameters to the function, the SequenceType of the result, and the body of the function.
[Definition: An anonymous function is a function item with no name. Anonymous functions may be created, for example, by evaluating an inline function expression or by partial function application.]
Note:
A more concise notation is introduced for simple functions in XPath 4.0 because it
can improve the readability of code
by reducing visual clutter. For example, a sort operation previously written as sort(//employee, (),
function($emp as element(employee)) as xs:string { $emp/@dateOfBirth })
can now be written
sort(//employee, (), ->{@dateOfBirth})
.
The use of the notation ->{expr}
mirrors the use of ->
as an arrow operator.
The full inline function syntax allows the names and types of the function argument to be declared, along with the type of the result:
function($x as xs:integer, $y as xs:integer) as xs:integer {$x + $y}
The types can be omitted:
function($x, $y) {$x + $y}
For brevity, the keyword function
can be replaced by the symbol ->
:
->($x, $y) {$x + $y}
This avoids visual clutter when a function is used as an argument to another function:
fn:for-each-pair($A, $B, ->($a, $b) {$a + $b})
The common case where a function accepts a single argument of type
item()
can be further abbreviated to ->{EXPR}
. This is equivalent to the
expanded syntax function($x as item()} as item()* {$x -> {EXPR}}
,
where x
is a system-allocated name that does not conflict with any user-defined variables. That is,
it defines an anonymous arity-one function, accepting any single item as its argument value, and returns the
result of evaluating the supplied expression with that item as the singleton focus.
For example, the following function call returns the sequence (2, 3, 4, 5, 6)
.
fn:for-each(1 to 5, ->{.+1})
A zero-arity function can be written as, for example, ->(){current-date()}
.
If a function parameter is declared using a name but no type, its default type is item()*
.
If the result type is omitted, its default result type is item()*
.
The parameters of an inline function expression are considered to be variables whose scope is the function body. It is a static error [err:XQST0039] for an inline function expression to have more than one parameter with the same name.
The static context for the function body is inherited from the location of the inline function expression, with the exception of the static type of the context item which is initially absentDM31.
The variables in scope for the function body include all variables representing the function parameters, as well as all variables that are in scope for the inline function expression.
Note:
Function parameter names can mask variables that would otherwise be in scope for the function body.
The result of an inline function expression is a single function with the following properties (as defined in Section 2.8.1 Functions DM31):
name: An absent name. Absent.
parameter names:
The parameter names in
the InlineFunctionExpr
's
ParamList
.
signature:
A FunctionTest
constructed from the
SequenceType
s in the InlineFunctionExpr
.
An implementation which can determine a more specific signature (for example, through use of type analysis of the function's body) is permitted to do so.
implementation:
The InlineFunctionExpr
's FunctionBody
.
nonlocal variable bindings:
For each nonlocal variable,
a binding of it to its value in the
variable values component
of the dynamic context of the InlineFunctionExpr
.
The following are examples of some inline function expressions:
This example creates a function that takes no arguments and returns a sequence of the first 6 primes:
function() as xs:integer+ { 2, 3, 5, 7, 11, 13 }
This example creates a function that takes two xs:double arguments and returns their product:
function($a as xs:double, $b as xs:double) as xs:double { $a * $b }
This example creates a function that prepends "$" to a supplied value:
->{"$" || .}
It is equivalent to the function concat("$", ?)
.
This example creates a function that returns the name
attribute of a supplied element node:
->{@name}
It is equivalent to the function function($x as item()) as item()* {$x ! @name}
.
[Definition: The coercion rules are rules used to convert a supplied value to a required type, for example when converting an argument of a function call to the declared type of the function parameter. ] The required type is expressed as a sequence type. The effect of the coercion rules may be to accept the value as supplied, to convert it to a value that matches the required type, or to reject it with a type error.
This section defines how the coercion rules operate; the situations in which the rules apply are defined elsewhere, by reference to this section.
Note:
In previous versions of this specification, the coercion rules were referred to as the function conversion rules. The terminology has changed because the rules are not exclusively associated with functions or function calling.
The coercion rules are applied to a supplied value V and a required sequence type T as follows:
If XPath
1.0 compatibility mode is true
and V
is not of the required type T, then the following conversions are applied
sequentially to V:
If T requires a single item or optional single item
(examples: xs:string
, xs:string?
,
xs:untypedAtomic
, xs:untypedAtomic?
,
node()
, node()?
, item()
,
item()?
), then V is effectively replaced by V[1]
.
If T is xs:string
or xs:string?
,
then V is effectively replaced by
fn:string(V)
.
Note:
This rule does not apply where T is derived from xs:string
or xs:string?
, because derived types did not arise in XPath 1.0.
If T is xs:double
or xs:double?
, then
V
is effectively replaced by fn:number(V)
.
Note:
This rule does not apply where T is derived from xs:double
or xs:double?
, because derived types did not arise in XPath 1.0.
Note:
The special rules for XPath 1.0 compatibility
mode are used for converting the arguments of a static function call, and
in certain XSLT constructs. They are not invoked in other contexts such as dynamic function calls,
for converting the result of an inline function to its required type,
for partial function application, or for implicit function calls such as
occur when evaluating functions such as fn:for-each
and fn:filter
.
If T is a SequenceType
whose ItemType
is a generalized atomic type
other than an enumeration type, (possibly with an occurrence indicator
*
, +
, or ?
), then the following conversions are applied,
in order:
TODO: coercion for enumeration types needs further work.
Atomization is applied to the given value, resulting in a sequence of atomic values.
Each item in the atomic sequence that is of type
xs:untypedAtomic
is cast to the expected
atomic type. If the expected atomic type is an
EnumerationType,
the value is cast to xs:string
. If the item is of type xs:untypedAtomic
and the expected type is namespace-sensitive, a type error
[err:XPTY0117] is raised.
For each numeric item in the atomic sequence that can be promoted to the expected atomic type using numeric promotion as described in B.1 Type Promotion, the promotion is done.
Note:
Numeric promotion is performed only when the required type is xs:double
or xs:float
(perhaps with an occurrence indicator). It is not performed
when the required type is derived from xs:double
or xs:float
.
For each item of type xs:anyURI
in the atomic sequence that can be promoted to the
expected atomic type using URI promotion as described in B.1 Type Promotion, the promotion is done.
Note:
Promotion of xs:anyURI
values is performed
only when the required type is xs:string
(perhaps with an occurrence indicator). It is not performed
when the required type is derived from xs:string
.
If T is a sequence type whose item type is an atomic type D, where D is derived from some primitive type P, then any atomic value A in the atomic sequence is relabeled as an instance of D if it satisfies all the following conditions:
A is an instance of P.
A is not an instance of D.
The datumDM40 of A is within the value space of D.
Relabeling an atomic value changes the type annotation but not the
datumDM40. For example, the
xs:integer
value 3 can be relabeled as an instance of xs:unsignedByte
, because
the datum is within the value space of xs:unsignedByte
.
Note:
Relabeling is not the same as casting. For example, the xs:decimal
value 10.1
can be cast to xs:integer
, but it cannot be relabeled as xs:integer
,
because its datum not within the value space of xs:integer
.
Note:
The effect of this rule is that if, for example, a function parameter is declared
with an expected type of xs:positiveInteger
, then a call that supplies the literal
value 3 will succeed, whereas a call that supplies -3 will fail.
Note:
This differs from previous versions of this specification, where both these calls would fail.
This change allows the arguments of existing functions to be defined with a
more precise type. For example, the $position
argument of array:get
can be defined as xs:positiveInteger
rather than xs:integer
. To enable
this to be done without breaking backwards compatibility in respect of error behavior,
built-in functions in many cases define custom error codes to be raised where
relabeling of argument values fails.
Note:
Numeric promotion and xs:anyURI
promotion occur only when T
is a primitive type (xs:double
, xs:float
, or xs:string
).
Relabeling occurs only when T is a derived type. Promotion and relabeling are therefore
never combined.
If T is a RecordTest (possibly with an occurrence indicator *
,
+
, or ?
), then V must be a map or sequence of maps, and the values of any
entries in these maps whose keys correspond to field declarations in the RecordTest
are converted
to the required type defined by that field declaration, by applying these rules recursively
(but with XPath 1.0 compatibility mode treated as false).
For example, if the required type is
record(longitude as xs:double, latitude as xs:double)
and the supplied value is map{"longitude": 0, "latitude":53.2}
,
then the map is converted to map{"longitude": 0.0e0, "latitude": 53.2e0}
.
If the
expected type is a TypedFunctionTest (possibly with an occurrence indicator *
,
+
, or ?
), function coercion is applied to each function in the given value.
Note:
Maps and arrays are functions, so function coercion applies to them as well.
If, after the above conversions, the resulting value does not match the expected type T according to the rules for SequenceType Matching, a type error is raised [err:XPTY0004].
Function coercion is a transformation applied to function items during application of the coercion rules. [Definition: Function coercion wraps a function item in a new function whose signature is the same as the expected type. This effectively delays the checking of the argument and return types until the function is called.]
Given a function F, and an expected function type, function coercion proceeds as follows:
If F has higher arity than the expected type, a type error is raised [err:XPTY0004]
If F has lower arity than the expected type, then F is wrapped in a new function that declares and ignores the additional argument; the following steps are then applied to this new function.
For example, if the expected type is function(node(), xs:boolean) as xs:string
,
and the supplied function is fn:name#1
, then the supplied function is effectively
replaced by function($n as node(), $b as xs:boolean) as xs:string {fn:name($n)}
Note:
This mechanism makes it easier to design versatile and extensible higher-order functions.
For example, in previous versions of this specification, the second argument of
the fn:filter
function expected an argument of type
function (item()) as xs:boolean
. This has now been extended to
function (item(), xs:integer) as xs:boolean
, but existing code continues
to work, because callback functions that are not interested in the value of the second
argument simply ignore it.
TODO: this change to fn:filter has not yet been made.
Function coercion then returns a new function item with the following properties (as defined in Section 2.8.1 Functions DM31):
name: The name of F (if not absent).
parameter names: The parameter names of F.
signature:
Annotations
is set to the annotations of F. TypedFunctionTest
is set to the expected type.
implementation:
In effect,
a FunctionBody
that calls F,
passing it the parameters of this new function,
in order.
nonlocal variable bindings: An empty mapping.
If the result of invoking the new function would necessarily result in a type error, that error may be raised during function coercion. It is implementation dependent whether this happens or not.
These rules have the following consequences:
SequenceType matching of the function's arguments and result are delayed until that function is called.
The coercion rules rules applied to the function's arguments and result are defined by the SequenceType it has most recently been coerced to. Additional coercion rules could apply when the wrapped function is called.
If an implementation has static type information about a function, that can be used to type check the function's argument and return types during static analysis.
Note:
Although the semantics of function coercion are specified in terms of wrapping the functions, static typing will often be able to reduce the number of places where this is actually necessary.
Since maps and arrays are also functions in XPath 4.0, function coercion applies to them as well. For instance, consider the following expression:
let $m := map { "Monday" : true(), "Wednesday" : true(), "Friday" : true(), "Saturday" : false(), "Sunday" : false() }, $days := ("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday") return fn:filter($days,$m)
The map $m
has a function signature of function(xs:anyAtomicType) as item()*
. When the fn:filter()
function is called, the following occurs to the map:
The map $m
is treated as function ($f)
, equivalent to map:get($m,?)
.
The coercion rules result in applying
function coercion
to $f
, wrapping $f
in a new function ($p
) with the
signature function(item()) as xs:boolean
.
$p
is matched against the SequenceType function(item()) as xs:boolean
, and succeeds.
When $p
is called by fn:filter()
, coercion
and SequenceType matching rules are applied to the argument, resulting in an item()
value
($a
) or a type error.
$f
is called with $a
, which returns an xs:boolean
or the empty sequence.
$p
applies coercion rule and SequenceType matching to the result sequence from $f
. When the result is an xs:boolean
the SequenceType matching succeeds. When it is an empty sequence (such as when $m
does not contain a key for "Tuesday"
), SequenceType matching results in a type error [err:XPTY0004], since the expected type is xs:boolean
and the actual type is an empty sequence.
Consider the following expression:
let $m := map { "Monday" : true(), "Tuesday" : false(), "Wednesday" : true(), "Thursday" : false(), "Friday" : true(), "Saturday" : false(), "Sunday" : false() } let $days := ("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday") return fn:filter($days,$m)
The result of the expression is the sequence ("Monday", "Wednesday", "Friday")
[60] | PostfixExpr |
::= |
PrimaryExpr (Predicate | PositionalArgumentList | Lookup)* |
|
[67] | Predicate |
::= | "[" Expr "]" |
|
[62] | PositionalArgumentList |
::= | "(" PositionalArguments? ")" |
|
[63] | PositionalArguments |
::= |
Argument ("," Argument)* |
|
[80] | Argument |
::= |
ExprSingle | ArgumentPlaceholder
|
[Definition: An
expression followed by a predicate (that is, E1[E2]
)
is referred to as a filter expression: its effect is
to return those items from the value of E1
that
satisfy the predicate in E2.] Filter expressions are
described in 4.5.1 Filter Expressions
An expression (other than a raw EQName) followed by an argument
list in parentheses (that is, E1(E2, E3, ...)
) is
referred to as a dynamic function call. Its
effect is to evaluate E1
to obtain a function,
and then call that function, with
E2
, E3
, ...
as
arguments. Dynamic function calls are described in 4.5.2 Dynamic Function Calls.
[60] | PostfixExpr |
::= |
PrimaryExpr (Predicate | PositionalArgumentList | Lookup)* |
|
[67] | Predicate |
::= | "[" Expr "]" |
A filter expression consists of a base expression followed by a predicate, which is an expression written in square brackets. The result of the filter expression consists of the items returned by the base expression, filtered by applying the predicate to each item in turn. The ordering of the items returned by a filter expression is the same as their order in the result of the primary expression.
Note:
Where the expression before the square brackets is a ReverseStep or ForwardStep, the expression is technically not a filter expression but an AxisStep. There are minor differences in the semantics: see 4.6.3 Predicates within Steps
Here are some examples of filter expressions:
Given a sequence of products in a variable, return only those products whose price is greater than 100.
$products[price gt 100]
List all the integers from 1 to 100 that are divisible by 5. (See 4.7.1 Sequence Concatenation for an explanation of the to
operator.)
(1 to 100)[. mod 5 eq 0]
The result of the following expression is the integer 25:
(21 to 29)[5]
The following example returns the fifth through ninth items in the sequence bound to variable $orders
.
$orders[fn:position() = (5 to 9)]
The following example illustrates the use of a filter expression as a step in a path expression. It returns the last chapter or appendix within the book bound to variable $book
:
$book/(chapter | appendix)[fn:last()]
For each item in the input sequence, the predicate expression is evaluated using an inner focus, defined as follows: The context item is the item currently being tested against the predicate. The context size is the number of items in the input sequence. The context position is the position of the context item within the input sequence.
For each item in the input sequence, the result of the
predicate expression is coerced to an xs:boolean
value, called the predicate truth value, as
described below. Those items for which the predicate truth value
is true
are retained, and those for which the
predicate truth value is false
are discarded.
The predicate truth value is derived by applying the following rules, in order:
If the value of the predicate expression is a singleton atomic value of a
numeric type or derived
from a numeric type,
the predicate truth value is true
if the value
of the predicate expression is equal (by the
eq
operator) to the context
position, and is false
otherwise.
Otherwise, the predicate truth value is the effective boolean value of the predicate expression.
[60] | PostfixExpr |
::= |
PrimaryExpr (Predicate | PositionalArgumentList | Lookup)* |
|
[61] | ArgumentList |
::= | "(" ((PositionalArguments ("," KeywordArguments)?) | KeywordArguments)? ")" |
|
[63] | PositionalArguments |
::= |
Argument ("," Argument)* |
|
[80] | Argument |
::= |
ExprSingle | ArgumentPlaceholder
|
|
[81] | ArgumentPlaceholder |
::= | "?" |
|
[64] | KeywordArguments |
::= |
KeywordArgument ("," KeywordArgument)* |
|
[65] | KeywordArgument |
::= |
EQName ":=" Argument
|
[Definition: A dynamic function call consists of a base expression that returns the function and a parenthesized list of zero or more arguments (argument expressions or ArgumentPlaceholders).]
A dynamic function call is evaluated as described in 4.4.2.1 Evaluating Dynamic Function Calls.
The following are examples of some dynamic function calls:
This example calls the function contained in $f, passing the arguments 2 and 3:
$f(2, 3)
This example fetches the second item from sequence $f, treats it as a function and calls it, passing an xs:string
argument:
$f[2]("Hi there")
This example calls the function $f
passing no arguments, and filters the result with a positional predicate:
$f()[2]
Note:
Arguments in a dynamic function call are always supplied positionally.
[47] | PathExpr |
::= | ("/" RelativePathExpr?) |
/* xgc: leading-lone-slash */ |
[48] | RelativePathExpr |
::= |
StepExpr (("/" | "//") StepExpr)* |
[Definition: A path expression can be used to locate nodes
within trees. A path expression consists of a series of one or more
steps, separated by "/
" or
"//
", and optionally beginning with
"/
" or "//
".] An initial
"/
" or "//
" is an abbreviation for
one or more initial steps that are implicitly added to the
beginning of the path expression, as described below.
A path expression consisting of a single step is evaluated as described in 4.6.2 Steps.
A "/
"
at the beginning of a path expression is an abbreviation for
the initial step (fn:root(self::node()) treat as document-node())/
(however, if the
"/
" is the entire path expression, the trailing "/
" is omitted from the expansion.) The effect
of this initial step is to begin the path at the root node of
the tree that contains the context node. If the context item
is not a node, a type
error is raised [err:XPTY0020]. At
evaluation time, if the root node of the context node is
not a document node, a dynamic error is
raised [err:XPDY0050].
A "//
" at the beginning of a path expression
is an abbreviation for the initial steps
(fn:root(self::node()) treat as
document-node())/descendant-or-self::node()/
(however, "//
" by itself is not a valid path expression [err:XPST0003].) The
effect of these initial steps is to establish an initial node
sequence that contains the root of the tree in which the
context node is found, plus all nodes descended from this
root.
This node sequence is used as the input to subsequent steps
in the path expression. If the context item is not a node, a
type error is
raised [err:XPTY0020]. At evaluation time, if the
root node of the context node is not a document node, a
dynamic error is
raised [err:XPDY0050].
Note:
The descendants of a node do not include attribute nodes or namespace nodes.
A path expression that starts with "/
"
or "//
" selects nodes starting from the root of
the tree containing the context item; it is often referred to
as an absolute path expression.
[48] | RelativePathExpr |
::= |
StepExpr (("/" | "//") StepExpr)* |
A relative path expression is a path expression that selects nodes within a tree by following a series of steps starting at the context node (which, unlike an absolute path expression, may be any node in a tree).
Each non-initial occurrence of "//
" in a path expression is
expanded as described in 4.6.5 Abbreviated Syntax, leaving a
sequence of steps separated by "/
". This sequence of steps
is then evaluated from left to right. So a path such as
E1/E2/E3/E4
is evaluated
as ((E1/E2)/E3)/E4
. The semantics of a path
expression are thus defined by the semantics of the
binary "/
" operator, which is defined in
4.6.1.1 Path operator (/).
Note:
Although the semantics describe the evaluation of a path with
more than two steps as proceeding from left to right, the "/
"
operator is in most cases associative, so evaluation from
right to left usually delivers the same result. The cases
where "/
" is not associative arise when the functions
fn:position()
and fn:last()
are
used: A/B/position()
delivers a sequence of
integers from 1 to the size of (A/B)
, whereas
A/(B/position())
restarts the counting at each B
element.
The following example illustrates the use of relative path expressions.
child::div1/child::para
Selects the
para
element children of the div1
element children of the context node; that is, the
para
element grandchildren of the context node
that have div1
parents.
Note:
Since each step in a path provides context nodes for the following step, in effect, only the last step in a path is allowed to return a sequence of non-nodes.
Note:
The "/
" character
can be used either as a complete path expression or as the
beginning of a longer path expression such as
"/*
". Also, "*
"
is both the multiply operator and a wildcard in path
expressions. This can cause parsing difficulties when
"/
" appears on the left-hand side of
"*
". This is resolved using the leading-lone-slash
constraint. For example, "/*
" and "/
*
" are valid path expressions containing wildcards,
but "/*5
" and "/ * 5
" raise syntax
errors. Parentheses must be used when "/
" is
used on the left-hand side of an operator, as in "(/) * 5
". Similarly, "4 + / *
5
" raises a syntax error, but "4 + (/) * 5
" is a valid expression.
The expression "4 + /
" is also
valid, because /
does not occur on the left-hand
side of the operator.
Similarly, in the expression /
union /*
, "union" is interpreted as an element name
rather than an operator. For it to be parsed as an operator,
the expression should be written (/)
union /*
.
/
)The path operator "/" is used to build expressions for locating nodes within trees. Its left-hand side expression must return a sequence of nodes. The operator returns either a sequence of nodes, in which case it additionally performs document ordering and duplicate elimination, or a sequence of non-nodes.
Each operation E1/E2
is evaluated as follows: Expression E1
is evaluated, and if the result is not a (possibly empty) sequence S
of nodes, a type error is raised [err:XPTY0019]. Each node in S
then serves in turn to provide an inner focus (the node as the context item, its position in S
as the context position, the length of S
as the context size) for an evaluation of E2
, as described in 2.2.2 Dynamic Context. The sequences resulting from all the evaluations of E2
are combined as follows:
If every evaluation of E2
returns a (possibly empty) sequence of nodes, these sequences are combined, and duplicate nodes are eliminated based on node identity.
The resulting node sequence is returned in document order.
If every evaluation of E2
returns a (possibly empty) sequence of non-nodes, these sequences are concatenated, in order, and returned.
The returned sequence preserves the orderings within and among the subsequences generated by the evaluations of E2
.
If the multiple evaluations of E2
return at least one node and at least one non-node, a type error is raised [err:XPTY0018].
Note:
The semantics of the path operator can also be defined using the simple map operator as follows (forming the union with an empty sequence ($R | ())
has the effect of eliminating duplicates and sorting nodes into document order):
E1/E2 ::= let $R := E1!E2 return if (every $r in $R satisfies $r instance of node()) then ($R|()) else if (every $r in $R satisfies not($r instance of node())) then $R else error()
[49] | StepExpr |
::= |
PostfixExpr | AxisStep
|
|
[50] | AxisStep |
::= | (ReverseStep | ForwardStep) PredicateList
|
|
[51] | ForwardStep |
::= | (ForwardAxis
NodeTest) | AbbrevForwardStep
|
|
[54] | ReverseStep |
::= | (ReverseAxis
NodeTest) | AbbrevReverseStep
|
|
[66] | PredicateList |
::= |
Predicate* |
[Definition: A step is a part of a path expression that generates a sequence of items and then filters the sequence by zero or more predicates. The value of the step consists of those items that satisfy the predicates, working from left to right. A step may be either an axis step or a postfix expression.] Postfix expressions are described in 4.5 Postfix Expressions.
[Definition: An axis step returns a sequence of nodes that are reachable from the context node via a specified axis. Such a step has two parts: an axis, which defines the "direction of movement" for the step, and a node test, which selects nodes based on their kind, name, and/or type annotation.] If the context item is a node, an axis step returns a sequence of zero or more nodes; otherwise, a type error is raised [err:XPTY0020]. The resulting node sequence is returned in document order. An axis step may be either a forward step or a reverse step, followed by zero or more predicates.
In the abbreviated syntax for a step, the axis can be omitted and other shorthand notations can be used as described in 4.6.5 Abbreviated Syntax.
The unabbreviated syntax for an axis step consists of the axis name
and node test separated by a double colon. The result of the step consists of the nodes
reachable from the context node via the specified axis that have the node kind, name,
and/or type annotation specified by the node test. For example, the
step child::para
selects the para
element children of the context node: child
is the name of the axis, and para
is the name of the element nodes to be selected on this axis. The available axes are described in 4.6.2.1 Axes. The
available node tests are described in 4.6.2.2 Node Tests. Examples of
steps are provided in 4.6.4 Unabbreviated Syntax and 4.6.5 Abbreviated Syntax.
[52] | ForwardAxis |
::= | ("child" "::") |
|
[55] | ReverseAxis |
::= | ("parent" "::") |
XPath defines a full set of axes for traversing documents, but a host language may define a subset of these axes. The following axes are defined:
The child
axis
contains the children of the context
node, which are the nodes returned by the
Section
5.3 children Accessor
DM31.
Note:
Only document nodes and element nodes have children. If the context node is any other kind of node, or if the context node is an empty document or element node, then the child axis is an empty sequence. The children of a document node or element node may be element, processing instruction, comment, or text nodes. Attribute, namespace, and document nodes can never appear as children.
the descendant
axis is defined as the transitive closure of
the child axis; it contains the descendants
of the context node (the children, the children of the children, and so on)
the parent
axis contains the sequence
returned by the
Section
5.11 parent Accessor
DM31,
which returns
the parent of the context
node, or an empty sequence
if the context node has no
parent
Note:
An attribute node may have an element node as its parent, even though the attribute node is not a child of the element node.
the
ancestor
axis is
defined as the transitive
closure of the parent axis; it
contains the ancestors of the
context node (the parent, the
parent of the parent, and so
on)
Note:
The ancestor axis includes the root node of the tree in which the context node is found, unless the context node is the root node.
the following-sibling
axis contains the context node's following
siblings, those children of the context
node's parent that occur after the context
node in document order; if the context node
is an attribute or namespace node, the
following-sibling
axis is
empty
the preceding-sibling
axis contains the context node's preceding
siblings, those children of the context
node's parent that occur before the context
node in document order; if the context node
is an attribute or namespace node, the
preceding-sibling
axis is
empty
the following
axis
contains all nodes that are
descendants of the root of the tree in
which the context node is found, are
not descendants of the context node,
and occur after the context node in
document order
the preceding
axis
contains all nodes that are
descendants of the root of the tree in
which the context node is found, are
not ancestors of the context node, and
occur before the context node in
document order
the attribute
axis
contains the attributes of the context node,
which are the nodes returned by the
Section
5.1 attributes Accessor
DM31
; the axis will be
empty unless the context node is an
element
the self
axis contains just the context node itself
the descendant-or-self
axis contains the context node and the descendants of the context
node
the ancestor-or-self
axis contains the context node and the ancestors of the context node;
thus, the ancestor-or-self axis will always include the root node
the namespace
axis
contains the namespace nodes of the
context node, which are the nodes
returned by the
Section
5.7 namespace-nodes Accessor
DM31; this axis
is empty unless the context node is an
element node. The
namespace
axis is
deprecated as of XPath 2.0. If XPath 1.0
compatibility mode is true
, the namespace
axis must be supported. If XPath 1.0
compatibility mode is false
, then support for the
namespace
axis is
implementation-defined. An implementation
that does not support the
namespace
axis when XPath 1.0
compatibility mode is false
must raise
a static
error
[err:XPST0010] if it is
used. Applications needing information
about the in-scope namespaces of an element
should use the functions
Section
10.2.6 fn:in-scope-prefixes
FO31,
and
Section
10.2.5 fn:namespace-uri-for-prefix
FO31.
Axes can be categorized as forward axes and reverse axes. An axis that only ever contains the context node or nodes that are after the context node in document order is a forward axis. An axis that only ever contains the context node or nodes that are before the context node in document order is a reverse axis.
The parent
, ancestor
, ancestor-or-self
, preceding
, and preceding-sibling
axes are reverse axes; all other axes are forward axes. The ancestor
, descendant
, following
, preceding
and self
axes partition a document (ignoring attribute and namespace nodes):
they do not overlap and together they contain all the nodes in the
document.
[Definition: Every axis has a principal node kind. If an axis can contain elements, then the principal node kind is element; otherwise, it is the kind of nodes that the axis can contain.] Thus:
For the attribute axis, the principal node kind is attribute.
For the namespace axis, the principal node kind is namespace.
For all other axes, the principal node kind is element.
[Definition: A node test is a condition on the name, kind (element, attribute, text, document, comment, or processing instruction), and/or type annotation of a node. A node test determines which nodes contained by an axis are selected by a step.]
[57] | NodeTest |
::= |
KindTest | NameTest
|
|
[58] | NameTest |
::= |
EQName | Wildcard
|
|
[59] | Wildcard |
::= | "*" |
/* ws: explicit */ |
[135] | EQName |
::= |
QName | URIQualifiedName
|
[Definition: A node test that consists only of an EQName or a
Wildcard is called a name test.] A name
test that consists of an EQName is true if and only if the kind of
the node is the principal node kind for the step axis and the
expanded QName of the node is equal (as defined by the eq
operator) to the
expanded QName specified by the name test. For
example, child::para
selects the para
element children of
the context node; if the context node has no
para
children, it selects an empty set
of nodes. attribute::abc:href
selects
the attribute of the context node with the QName
abc:href
; if the context node has no
such attribute, it selects an empty set of
nodes.
If the EQName is a lexical QName, it is resolved into an expanded QName using the statically known namespaces in the expression context. It is a static error [err:XPST0081] if the QName has a prefix that does not correspond to any statically known namespace. An unprefixed QName, when used as a name test on an axis whose principal node kind is element, has the namespace URI of the default element namespace in the expression context; otherwise, it has no namespace URI.
A name test is not satisfied by an element node whose name does not match the expanded QName of the name test, even if it is in a substitution group whose head is the named element.
A node test *
is true for any node of the
principal node
kind of the step axis. For example, child::*
will select all element
children of the context node, and attribute::*
will select all
attributes of the context node.
A node test can have the form
NCName:*
. In this case, the prefix is
expanded in the same way as with a lexical QName, using the
statically known
namespaces in the static context. If
the prefix is not found in the statically known namespaces,
a static
error is raised [err:XPST0081].
The node test is true for any node of the principal
node kind of the step axis whose expanded QName has the namespace URI
to which the prefix is bound, regardless of the
local part of the name.
A node test can contain a BracedURILiteral, e.g.
Q{http://example.com/msg}*
Such a node test is true for any node of the principal node kind of the step axis whose expanded QName has the namespace URI specified in the BracedURILiteral, regardless of the local part of the name.
A node test can also
have the form *:NCName
. In this case,
the node test is true for any node of the principal
node kind of the step axis whose local name matches the given NCName,
regardless of its namespace or lack of a namespace.
[Definition: An alternative form of a node test called a kind test can select nodes based on their kind, name, and type annotation.] The syntax and semantics of a kind test are described in 3.4 Sequence Types and 3.5 Sequence Type Matching. When a kind test is used in a node test, only those nodes on the designated axis that match the kind test are selected. Shown below are several examples of kind tests that might be used in path expressions:
node()
matches any
node.
text()
matches
any text
node.
comment()
matches any comment
node.
namespace-node()
matches any
namespace node.
element()
matches any element
node.
schema-element(person)
matches any element node whose name is
person
(or is in the substitution group
headed by person
), and whose type
annotation is the same as (or is derived from) the declared type of the person
element in the in-scope element declarations.
element(person)
matches any element node whose name is
person
, regardless of its type annotation.
element(person, surgeon)
matches any non-nilled element node whose name
is person
, and whose type
annotation is
surgeon
or is derived from surgeon
.
element(*,
surgeon)
matches any non-nilled element node whose type
annotation is surgeon
(or is derived from surgeon
), regardless of
its
name.
attribute()
matches any
attribute node.
attribute(price)
matches
any attribute whose name is price
,
regardless of its type annotation.
attribute(*,
xs:decimal)
matches any attribute whose type
annotation is xs:decimal
(or is derived from xs:decimal
), regardless of
its
name.
document-node()
matches any document
node.
document-node(element(book))
matches any document node whose content consists of
a single element node that satisfies the kind test
element(book)
, interleaved with zero or more
comments and processing
instructions.
[50] | AxisStep |
::= | (ReverseStep | ForwardStep) PredicateList
|
|
[66] | PredicateList |
::= |
Predicate* |
|
[67] | Predicate |
::= | "[" Expr "]" |
A predicate within a Step has similar syntax and semantics to a predicate within a filter expression. The only difference is in the way the context position is set for evaluation of the predicate.
For the purpose of evaluating the context position within a predicate, the input sequence is considered to be sorted as follows: into document order if the predicate is in a forward-axis step, into reverse document order if the predicate is in a reverse-axis step, or in its original order if the predicate is not in a step.
Here are some examples of axis steps that contain predicates:
This example selects the second chapter
element that is a child
of the context node:
child::chapter[2]
This example selects all the descendants of the
context node that are elements named
"toy"
and whose color
attribute has the value "red"
:
descendant::toy[attribute::color = "red"]
This example selects all the employee
children of the context node
that have both a secretary
child element and an assistant
child element:
child::employee[secretary][assistant]
Note:
When using predicates with a sequence of nodes selected using a
reverse axis, it is important to remember that the
context positions for such a sequence are assigned in reverse
document order. For example, preceding::foo[1]
returns the first qualifying foo
element in reverse document order, because the predicate is part of an axis step using a reverse axis. By
contrast, (preceding::foo)[1]
returns the first qualifying foo
element in document order, because the parentheses cause (preceding::foo)
to be parsed as a primary expression in which context positions are assigned in document order. Similarly, ancestor::*[1]
returns the nearest ancestor element, because the ancestor
axis is a
reverse axis, whereas (ancestor::*)[1]
returns the root element (first ancestor in document order).
The fact that a reverse-axis step assigns context positions in reverse document order for the purpose of evaluating predicates does not alter the fact that the final result of the step is always in document order.
This section provides a number of examples of path expressions in which the axis is explicitly specified in each step. The syntax used in these examples is called the unabbreviated syntax. In many common cases, it is possible to write path expressions more concisely using an abbreviated syntax, as explained in 4.6.5 Abbreviated Syntax.
child::para
selects
the para
element children of the context node
child::*
selects all element children of the context node
child::text()
selects all text node children of the context node
child::node()
selects all the children of the context node. Note that no attribute nodes are returned, because attributes are not children.
attribute::name
selects the name
attribute of the context node
attribute::*
selects all the attributes of the context node
parent::node()
selects the parent of the context node. If the context node is an attribute node, this expression returns the element node (if any) to which the attribute node is attached.
descendant::para
selects the para
element descendants of the context node
ancestor::div
selects all div
ancestors of the context node
ancestor-or-self::div
selects the div
ancestors of the context node and, if the context node is a div
element, the context node as well
descendant-or-self::para
selects the para
element descendants of the context node and, if the context node is a para
element, the context node as well
self::para
selects the context node if it is a para
element, and otherwise returns an empty sequence
child::chapter/descendant::para
selects the para
element
descendants of the chapter
element children of the context node
child::*/child::para
selects all para
grandchildren of the context node
/
selects the root of the tree that contains the context node, but raises a dynamic error if this root is not a document node
/descendant::para
selects all the para
elements in the same document as the context node
/descendant::list/child::member
selects all
the member
elements that have a list
parent and that are in the same document as the context node
child::para[fn:position() = 1]
selects the first para
child of the context node
child::para[fn:position() = fn:last()]
selects the last para
child of the context node
child::para[fn:position() = fn:last()-1]
selects the last but one para
child of the context node
child::para[fn:position() > 1]
selects all the para
children of the context node other than the first para
child of the context node
following-sibling::chapter[fn:position() = 1]
selects the next chapter
sibling of the context node
preceding-sibling::chapter[fn:position() = 1]
selects the previous chapter
sibling of the context node
/descendant::figure[fn:position() = 42]
selects the forty-second figure
element in the document containing the context node
/child::book/child::chapter[fn:position() = 5]/child::section[fn:position() = 2]
selects the
second section
of the fifth chapter
of the book
whose parent is the document node that contains the context node
child::para[attribute::type eq "warning"]
selects
all para
children of the context node that have a type
attribute with value warning
child::para[attribute::type eq 'warning'][fn:position() = 5]
selects the fifth para
child of the context node that has a type
attribute with value warning
child::para[fn:position() = 5][attribute::type eq "warning"]
selects the fifth para
child of the context node if that child has a type
attribute with value warning
child::chapter[child::title = 'Introduction']
selects
the chapter
children of the context node that have one or
more title
children whose typed value is equal to the
string Introduction
child::chapter[child::title]
selects the chapter
children of the context node that have one or more title
children
child::*[self::chapter or self::appendix]
selects the chapter
and appendix
children of the context node
child::*[self::chapter or
self::appendix][fn:position() = fn:last()]
selects the
last chapter
or appendix
child of the context node
[53] | AbbrevForwardStep |
::= | "@"? NodeTest
|
|
[56] | AbbrevReverseStep |
::= | ".." |
The abbreviated syntax permits the following abbreviations:
The attribute axis attribute::
can be
abbreviated by @
. For example, a path expression para[@type="warning"]
is short
for child::para[attribute::type="warning"]
and
so selects para
children with a type
attribute with value
equal to warning
.
If the axis name is omitted from an axis step, the default axis is
child
, with two exceptions:
(1) if the NodeTest in an axis step contains an AttributeTest or SchemaAttributeTest then the
default axis is attribute
;
(2) if the NodeTest in an axis step is a NamespaceNodeTest
then the default axis is namespace
- in an implementation that does not support
the namespace axis, an error is raised [err:XQST0134].
Note:
The namespace axis is deprecated as of XPath 2.0, but required in some languages that use XPath, including XSLT.
For example, the path expression section/para
is an abbreviation for child::section/child::para
, and the path
expression section/@id
is an
abbreviation for child::section/attribute::id
. Similarly,
section/attribute(id)
is an
abbreviation for child::section/attribute::attribute(id)
. Note
that the latter expression contains both an axis specification and
a node test.
Each non-initial occurrence of //
is effectively replaced by /descendant-or-self::node()/
during processing of a path expression. For example, div1//para
is
short for child::div1/descendant-or-self::node()/child::para
and so will select all para
descendants of div1
children.
Note:
The path expression //para[1]
does not mean the same as the path
expression /descendant::para[1]
. The latter selects the first descendant para
element; the former
selects all descendant para
elements that are the first para
children of their respective parents.
A step consisting
of ..
is short
for parent::node()
. For example, ../title
is short for parent::node()/child::title
and so will select the title
children of the parent of the context node.
Note:
The expression .
, known as a context item
expression, is a primary expression,
and is described in 4.3.4 Context Item Expression.
Here are some examples of path expressions that use the abbreviated syntax:
para
selects the para
element children of the context node
*
selects all element children of the context node
text()
selects all text node children of the context node
@name
selects
the name
attribute of the context node
@*
selects all the attributes of the context node
para[1]
selects the first para
child of the context node
para[fn:last()]
selects the last para
child of the context node
*/para
selects
all para
grandchildren of the context node
/book/chapter[5]/section[2]
selects the
second section
of the fifth chapter
of the book
whose parent is the document node that contains the context node
chapter//para
selects the para
element descendants of the chapter
element children of the context node
//para
selects all
the para
descendants of the root document node and thus selects all para
elements in the same document as the context node
//@version
selects all the version
attribute nodes that are in the same document as the context node
//list/member
selects all the member
elements in the same document as the context node that have a list
parent
.//para
selects
the para
element descendants of the context node
..
selects the parent of the context node
../@lang
selects
the lang
attribute of the parent of the context node
para[@type="warning"]
selects all para
children of the context node that have a type
attribute with value warning
para[@type="warning"][5]
selects the fifth para
child of the context node that has a type
attribute with value warning
para[5][@type="warning"]
selects the fifth para
child of the context node if that child has a type
attribute with value warning
chapter[title="Introduction"]
selects the chapter
children of the context node that have one
or more title
children whose typed value is equal to the string Introduction
chapter[title]
selects the chapter
children of the context node that have one or more title
children
employee[@secretary and @assistant]
selects all
the employee
children of the context node that have both a secretary
attribute and
an assistant
attribute
book/(chapter|appendix)/section
selects
every section
element that has a parent that is either a chapter
or an appendix
element, that in turn is a child of a book
element that is a child of the context node.
If E
is any expression that returns a sequence of nodes, then the expression E/.
returns the same nodes in document order, with duplicates eliminated based on node identity.
XPath 4.0 supports operators to construct, filter, and combine
sequences of items.
Sequences are never nested—for
example, combining the values 1
, (2, 3)
, and ( )
into a single sequence results
in the sequence (1, 2, 3)
.
[10] | Expr |
::= |
ExprSingle ("," ExprSingle)* |
[Definition: One way to construct a sequence is by using the comma operator, which evaluates each of its operands and concatenates the resulting sequences, in order, into a single result sequence.] Empty parentheses can be used to denote an empty sequence.
A sequence may contain duplicate items, but a sequence is never an item in another sequence. When a new sequence is created by concatenating two or more input sequences, the new sequence contains all the items of the input sequences and its length is the sum of the lengths of the input sequences.
Note:
In places where the grammar calls for ExprSingle, such as the arguments of a function call, any expression that contains a top-level comma operator must be enclosed in parentheses.
Here are some examples of expressions that construct sequences:
The result of this expression is a sequence of five integers:
(10, 1, 2, 3, 4)
This expression combines four sequences of length one, two, zero, and two, respectively, into a single sequence of length five. The result of this expression is the sequence 10, 1, 2, 3, 4
.
(10, (1, 2), (), (3, 4))
The result of this expression is a sequence containing
all salary
children of the context node followed by all bonus
children.
(salary, bonus)
Assuming that $price
is bound to
the value 10.50
, the result of this expression is the sequence 10.50, 10.50
.
($price, $price)
[28] | RangeExpr |
::= |
AdditiveExpr ( "to" AdditiveExpr )? |
A RangeExpression can be used to construct a sequence of
integers. Each of the operands is
converted as though it was an argument of a function with the expected
parameter type xs:integer?
.
If either operand is an empty sequence, or if the integer derived from the first operand is greater than the integer derived from the second operand, the result of the range expression is an empty sequence. If the two operands convert to the same integer, the result of the range expression is that integer. Otherwise, the result is a sequence containing the two integer operands and
every integer between the two operands, in increasing order.
The following examples illustrate the semantics:
1 to 4
returns the sequence 1, 2, 3, 4
10 to 10
returns the singleton sequence 10
10 to 1
returns the empty sequence
-13 to -10
returns the sequence -13, -12, -11, -10
More formally, a RangeExpression is evaluated as follows:
Each of the operands of the to
operator is converted as though it was an argument of a function
with the expected parameter type xs:integer?
.
If either operand is an empty sequence, or if the integer derived from the first operand is greater than the integer derived from the second operand, the result of the range expression is an empty sequence.
If the two operands convert to the same integer, the result of the range expression is that integer.
Otherwise, the result is a sequence containing the two integer operands and every integer between the two operands, in increasing order.
The following examples illustrate the use of RangeExpressions
.
This example uses a range expression as one operand in constructing a sequence.
It evaluates to the sequence 10, 1, 2, 3, 4
.
(10, 1 to 4)
This example selects the first four items from an input sequence:
$input[position() = 1 to 4]
This example returns the sequence (0, 0.1, 0.2, 0.3, 0.5):
$x = (1 to 5)!.*0.1
This example constructs a sequence of length one containing the single integer 10.
10 to 10
The result of this example is a sequence of length zero.
15 to 10
This example uses the fn:reverse function to construct a sequence of six integers in decreasing order. It evaluates to the sequence 15, 14, 13, 12, 11, 10.
fn:reverse(10 to 15)
[32] | UnionExpr |
::= |
IntersectExceptExpr ( ("union" | "|") IntersectExceptExpr )* |
|
[33] | IntersectExceptExpr |
::= |
InstanceofExpr ( ("intersect" | "except") InstanceofExpr )* |
XPath 4.0 provides the following operators for combining sequences of nodes:
The union
and |
operators are equivalent. They take two node sequences as operands and
return a sequence containing all the nodes that occur in either of the
operands.
The intersect
operator takes two node sequences as operands and returns a sequence
containing all the nodes that occur in both operands.
The except
operator takes two node sequences as operands and returns a sequence
containing all the nodes that occur in the first operand but not in the second
operand.
All these operators eliminate duplicate nodes from their result sequences based on node identity. The resulting sequence is returned in document order.
If an operand
of union
, intersect
, or except
contains an item that is not a node, a type error is raised [err:XPTY0004].
If an IntersectExceptExpr contains more than two InstanceofExprs, they are grouped from left to right. With a UnionExpr, it makes no difference how operands are grouped, the results are the same.
Here are some examples of expressions that combine sequences. Assume the existence of three element nodes that we will refer to by symbolic names A, B, and C. Assume that the variables $seq1
, $seq2
and $seq3
are bound to the following sequences of these nodes:
$seq1
is bound to (A, B)
$seq2
is bound to (A, B)
$seq3
is bound to (B, C)
Then:
$seq1 union $seq2
evaluates to the sequence (A, B).
$seq2 union $seq3
evaluates to the sequence (A, B, C).
$seq1 intersect $seq2
evaluates to the sequence (A, B).
$seq2 intersect $seq3
evaluates to the sequence containing B only.
$seq1 except $seq2
evaluates to the empty sequence.
$seq2 except $seq3
evaluates to the sequence containing A only.
In addition to the sequence operators described here, see Section 14 Functions and operators on sequences FO31 for functions defined on sequences.
XPath 4.0 provides arithmetic operators for addition, subtraction, multiplication, division, and modulus, in their usual binary and unary forms.
[29] | AdditiveExpr |
::= |
MultiplicativeExpr ( ("+" | "-") MultiplicativeExpr )* |
|
[30] | MultiplicativeExpr |
::= |
OtherwiseExpr ( ("*" | "div" | "idiv" | "mod") OtherwiseExpr )* |
|
[39] | UnaryExpr |
::= | ("-" | "+")* ValueExpr
|
|
[40] | ValueExpr |
::= |
SimpleMapExpr
|
A subtraction operator must be preceded by whitespace if
it could otherwise be interpreted as part of the previous token. For
example, a-b
will be interpreted as a
name, but a - b
and a -b
will be interpreted as arithmetic expressions. (See A.2.4 Whitespace Rules for further details on whitespace handling.)
If an AdditiveExpr contains more than two MultiplicativeExprs, they are grouped from left to right. So, for instance,
A - B + C - D
is equivalent to
((A - B) + C) - D
Similarly, the operands of a MultiplicativeExpr are grouped from left to right.
The first step in evaluating an arithmetic expression is to evaluate its operands. The order in which the operands are evaluated is implementation-dependent.
If XPath 1.0 compatibility mode is true
, each operand is evaluated by applying the following steps, in order:
Atomization is applied to the operand. The result of this operation is called the atomized operand.
If the atomized operand is an empty sequence, the result of
the arithmetic expression is the xs:double
value NaN
, and the implementation
need not evaluate the other operand or apply the operator. However,
an implementation may choose to evaluate the other operand in order
to determine whether it raises an error.
If the atomized operand is a sequence of length greater than one, any items after the first item in the sequence are discarded.
If the atomized operand is now an instance of type xs:boolean
, xs:string
,
xs:decimal
(including xs:integer
), xs:float
, or xs:untypedAtomic
, then it
is converted to the type xs:double
by applying the fn:number
function. (Note that fn:number
returns the value NaN
if its operand cannot be converted to a number.)
If XPath 1.0 compatibility mode is false
, each
operand is evaluated by applying the following steps, in order:
Atomization is applied to the operand. The result of this operation is called the atomized operand.
If the atomized operand is an empty sequence, the result of the arithmetic expression is an empty sequence, and the implementation need not evaluate the other operand or apply the operator. However, an implementation may choose to evaluate the other operand in order to determine whether it raises an error.
If the atomized operand is a sequence of length greater than one, a type error is raised [err:XPTY0004].
If the atomized operand is of type xs:untypedAtomic
, it is cast to xs:double
. If
the cast fails, a dynamic
error is raised. [err:FORG0001]FO31
After evaluation of the operands, if the types of the operands are a valid combination for the given arithmetic operator, the operator is applied to the operands, resulting in an atomic value or a dynamic error (for example, an error might result from dividing by zero.) The combinations of atomic types that are accepted by the various arithmetic operators, and their respective result types, are listed in B.2 Operator Mapping together with the operator functions that define the semantics of the operator for each type combination, including the dynamic errors that can be raised by the operator. The definitions of the operator functions are found in [XQuery and XPath Functions and Operators 4.0].
If the types of the operands, after evaluation, are not a valid combination for the given operator, according to the rules in B.2 Operator Mapping, a type error is raised [err:XPTY0004].
XPath 4.0 supports two division operators named div
and idiv
. Each of these operators accepts two operands of any numeric type.
The semantics of div
are defined in Section
4.2.5 op:numeric-integer-divide
FO31.
The semantics of idiv
are defined in Section
4.2.4 op:numeric-divide
FO31.
Here are some examples of arithmetic expressions:
The first expression below returns the xs:decimal
value -1.5
, and the second expression returns the xs:integer
value -1
:
-3 div 2 -3 idiv 2
Subtraction of two date values results in a value of type xs:dayTimeDuration
:
$emp/hiredate - $emp/birthdate
This example illustrates the difference between a subtraction operator and a hyphen:
$unit-price - $unit-discount
Unary operators have higher precedence than binary operators (other than "!
", "/
", and "[]
"), subject of
course to the use of parentheses. Therefore, the following two examples have different meanings:
-$bellcost + $whistlecost -($bellcost + $whistlecost)
Note:
Multiple consecutive unary arithmetic operators are permitted.
[27] | StringConcatExpr |
::= |
RangeExpr ( "||" RangeExpr )* |
String concatenation expressions allow the string representations of values to be concatenated. In XPath 4.0, $a || $b
is equivalent to fn:concat($a, $b)
. The following expression evaluates to the string concatenate
:
"con" || "cat" || "enate"
Comparison expressions allow two values to be compared. XPath 4.0 provides three kinds of comparison expressions, called value comparisons, general comparisons, and node comparisons.
[26] | ComparisonExpr |
::= |
StringConcatExpr ( (ValueComp
|
|
[44] | ValueComp |
::= | "eq" | "ne" | "lt" | "le" | "gt" | "ge" |
|
[43] | GeneralComp |
::= | "=" | "!=" | "<" | "<=" | ">" | ">=" |
|
[45] | NodeComp |
::= | "is" | "<<" | ">>" |
Note:
When an XPath expression is written
within an XML document, the XML escaping rules for special characters
must be followed; thus "<
" must be written as
"<
".
The value comparison operators are eq
, ne
, lt
, le
, gt
, and ge
. Value comparisons are used for comparing single values.
The first step in evaluating a value comparison is to evaluate its operands. The order in which the operands are evaluated is implementation-dependent. Each operand is evaluated by applying the following steps, in order:
Atomization is applied to each operand. The result of this operation is called the atomized operand.
If an atomized operand is an empty sequence, the result of the value comparison is an empty sequence, and the implementation need not evaluate the other operand or apply the operator. However, an implementation may choose to evaluate the other operand in order to determine whether it raises an error.
If an atomized operand is a sequence of length greater than one, a type error is raised [err:XPTY0004].
If an atomized operand is of type
xs:untypedAtomic
, it is cast to
xs:string
.
Note:
The purpose of this rule is to
make value comparisons transitive. Users should be aware that the
general comparison operators have a different rule for casting of
xs:untypedAtomic
operands. Users should also be aware
that transitivity of value comparisons may be compromised by loss of
precision during type conversion (for example, two
xs:integer
values that differ slightly may both be
considered equal to the same xs:float
value because
xs:float
has less precision than
xs:integer
).
If the two operands are instances of different primitive types (meaning the 19 primitive types defined in Section 3.2 Primitive datatypesXS2), then:
If each operand is an instance of one of the types xs:string
or xs:anyURI
, then both operands are cast to type xs:string
.
If each operand is an instance of one of the types xs:decimal
or xs:float
, then both operands are cast to type xs:float
.
If each operand is an instance of one of the types xs:decimal
, xs:float
, or xs:double
, then both operands are cast to type xs:double
.
Otherwise, a type error is raised [err:XPTY0004].
Note:
The primitive type of an xs:integer
value for this purpose is xs:decimal
.
Finally, if the types of the operands are a valid combination for the given operator, the operator is applied to the operands.
The combinations of atomic types that are accepted by the various value comparison operators, and their respective result types, are listed in B.2 Operator Mapping together with the operator functions that define the semantics of the operator for each type combination. The definitions of the operator functions are found in [XQuery and XPath Functions and Operators 4.0].
Informally, if both atomized operands consist of exactly one atomic
value, then the result of the comparison is true
if the value of the
first operand is (equal, not equal, less than, less than or equal,
greater than, greater than or equal) to the value of the second
operand; otherwise the result of the comparison is false
.
If the types of the operands, after evaluation, are not a valid combination for the given operator, according to the rules in B.2 Operator Mapping, a type error is raised [err:XPTY0004].
Here are some examples of value comparisons:
The following comparison atomizes the node(s) that are returned by the expression $book/author
. The comparison is true only if the result of atomization is the value "Kennedy" as an instance of xs:string
or xs:untypedAtomic
. If the result of atomization is an empty sequence, the result of the comparison is an empty sequence. If the result of atomization is a sequence containing more than one value, a type error is raised [err:XPTY0004].
$book1/author eq "Kennedy"
The following comparison is true
because atomization converts an array to its member sequence:
[ "Kennedy" ] eq "Kennedy"
The following path expression contains a predicate that selects products whose weight is greater than 100. For any product that does not have a weight
subelement, the value of the predicate is the empty sequence, and the product is not selected. This example assumes that weight
is a validated element with a numeric type.
//product[weight gt 100]
The following comparison is true if my:hatsize
and my:shoesize
are both user-defined types that are derived by restriction from a primitive numeric type:
my:hatsize(5) eq my:shoesize(5)
The following comparison is true. The eq
operator compares two QNames by performing codepoint-comparisons of their namespace URIs and their local names, ignoring their namespace prefixes.
fn:QName("http://example.com/ns1", "this:color") eq fn:QName("http://example.com/ns1", "that:color")
The general comparison operators are =
, !=
, <
, <=
, >
, and >=
. General comparisons are existentially quantified comparisons that may be applied to operand sequences of any length. The result of a general comparison that does not raise an error is
always true
or false
.
If XPath 1.0 compatibility mode is true
, a general comparison is evaluated by applying the following rules, in order:
If either operand is a single atomic value that is an instance of
xs:boolean
, then the other operand is converted to xs:boolean
by taking its
effective boolean value.
Atomization is applied to each operand. After atomization, each operand is a sequence of atomic values.
If the comparison operator is <
, <=
, >
, or >=
, then each item in both of the
operand sequences is converted to the type xs:double
by applying the
fn:number
function. (Note that fn:number
returns the value NaN
if its operand cannot be converted to a number.)
The result of the comparison is true
if and only if there is a pair of
atomic values, one in the first operand sequence and the other in the second operand sequence, that have the required
magnitude relationship. Otherwise the result of the comparison is
false
or an error. The magnitude relationship between two atomic values is determined by
applying the following rules. If a cast
operation called for by these rules is not successful, a dynamic error is raised. [err:FORG0001]FO31
If at least one of the two atomic values is an instance of a numeric type, then both atomic values are converted to the type xs:double
by
applying the fn:number
function.
If at least one of the two atomic values is an instance of xs:string
,
or if both atomic values are instances of xs:untypedAtomic
, then both
atomic values are cast to the type xs:string
.
If one of the atomic values is an instance of xs:untypedAtomic
and the other is not an instance of xs:string
, xs:untypedAtomic
, or any numeric type, then the xs:untypedAtomic
value is
cast to the dynamic type of the other value.
After performing the conversions described above, the atomic values are
compared using one of the value comparison operators eq
, ne
, lt
, le
, gt
, or
ge
, depending on whether the general comparison operator was =
, !=
, <
, <=
,
>
, or >=
. The values have the required magnitude relationship if and only if the result
of this value comparison is true
.
If XPath 1.0 compatibility mode is false
, a
general comparison is evaluated by applying the following rules, in order:
Atomization is applied to each operand. After atomization, each operand is a sequence of atomic values.
The result of the comparison is true
if and only if there is a pair of
atomic values, one in the first operand sequence and the other in the second operand sequence, that have the required
magnitude relationship. Otherwise the result of the comparison is
false
or an error. The magnitude relationship between two atomic values is determined by
applying the following rules. If a cast
operation called for by these rules is not successful, a dynamic error is raised. [err:FORG0001]FO31
If both atomic values are instances of xs:untypedAtomic
,
then the values are cast to the type xs:string
.
If exactly one of the atomic values is an instance of
xs:untypedAtomic
, it is cast to a type depending on
the other value's dynamic type T according to the following rules,
in which V denotes the value to be cast:
If T is a numeric type or is derived from a numeric type,
then V is cast to xs:double
.
If T is xs:dayTimeDuration
or is derived from
xs:dayTimeDuration
,
then V is cast to xs:dayTimeDuration
.
If T is xs:yearMonthDuration
or is derived from
xs:yearMonthDuration
,
then V is cast to xs:yearMonthDuration
.
In all other cases, V is cast to the primitive base type of T.
Note:
The special treatment of the duration types is required to avoid
errors that may arise when comparing the primitive type
xs:duration
with any duration type.
After performing the conversions described above, the atomic values are
compared using one of the value comparison operators eq
, ne
, lt
, le
, gt
, or
ge
, depending on whether the general comparison operator was =
, !=
, <
, <=
,
>
, or >=
. The values have the required magnitude relationship if and only if the result
of this value comparison is true
.
When evaluating a general comparison in which either operand is a sequence of items, an implementation may return true
as soon as it finds an item in the first operand and an item in the second operand that have the required magnitude relationship. Similarly, a general comparison may raise a dynamic error as soon as it encounters an error in evaluating either operand, or in comparing a pair of items from the two operands. As a result of these rules, the result of a general comparison is not deterministic in the presence of errors.
Here are some examples of general comparisons:
The following comparison is true if the typed value of any
author
subelement of $book1
is "Kennedy" as an instance of xs:string
or xs:untypedAtomic
:
$book1/author = "Kennedy"
The following comparison is true
because atomization converts an array to its member sequence:
[ "Obama", "Nixon", "Kennedy" ] = "Kennedy"
The following example contains three general comparisons. The value of the first two comparisons is true
, and the value of the third comparison is false
. This example illustrates the fact that general comparisons are not transitive.
(1, 2) = (2, 3) (2, 3) = (3, 4) (1, 2) = (3, 4)
The following example contains two general comparisons, both of which are true
. This example illustrates the fact that the =
and !=
operators are not inverses of each other.
(1, 2) = (2, 3) (1, 2) != (2, 3)
Suppose that $a
, $b
, and $c
are bound to element nodes with type annotation xs:untypedAtomic
, with string values "1
", "2
", and "2.0
" respectively. Then ($a, $b) = ($c, 3.0)
returns false
, because $b
and $c
are compared as strings. However, ($a, $b) = ($c, 2.0)
returns true
, because $b
and 2.0
are compared as numbers.
Node comparisons are used to compare two nodes, by their identity or by their document order. The result of a node comparison is defined by the following rules:
The operands of a node comparison are evaluated in implementation-dependent order.
If either operand is an empty sequence, the result of the comparison is an empty sequence, and the implementation need not evaluate the other operand or apply the operator. However, an implementation may choose to evaluate the other operand in order to determine whether it raises an error.
Each operand must be either a single node or an empty sequence; otherwise a type error is raised [err:XPTY0004].
A comparison with the is
operator is true
if the two operand nodes are the same node; otherwise it
is false
. See [XQuery and XPath Data Model (XDM) 3.1] for the definition of node identity.
A comparison with the <<
operator returns true
if the left operand node precedes the right operand node in
document order; otherwise it returns false
.
A comparison with the >>
operator returns true
if the left operand node follows the right operand node in
document order; otherwise it returns false
.
Here are some examples of node comparisons:
The following comparison is true only if the left and right sides each evaluate to exactly the same single node:
/books/book[isbn="1558604820"] is /books/book[call="QA76.9 C3845"]
The following comparison is true only if the node identified by the left side occurs before the node identified by the right side in document order:
/transactions/purchase[parcel="28-451"] << /transactions/sale[parcel="33-870"]
A logical expression is either an and-expression or
an or-expression. If a logical expression does not raise an error, its value is always one
of the boolean values true
or false
.
[24] | OrExpr |
::= |
AndExpr ( "or" AndExpr )* |
|
[25] | AndExpr |
::= |
ComparisonExpr ( "and" ComparisonExpr )* |
The first step in evaluating a logical expression is to find the effective boolean value of each of its operands (see 2.5.3 Effective Boolean Value).
The value of an and-expression is determined by the effective boolean values (EBV's) of its operands, as shown in the following table:
AND: | EBV2 =
true
|
EBV2 = false
|
error in EBV2 |
---|---|---|---|
EBV1 =
true
|
true
|
false
|
error |
EBV1
= false
|
false
|
false
|
if XPath 1.0 compatibility mode is true , then false ; otherwise either false or error.
|
error in EBV1 | error |
if XPath 1.0 compatibility mode is true , then error; otherwise either false or error.
|
error |
The value of an or-expression is determined by the effective boolean values (EBV's) of its operands, as shown in the following table:
OR: | EBV2 =
true
|
EBV2 = false
|
error in EBV2 |
---|---|---|---|
EBV1 =
true
|
true
|
true
|
if XPath 1.0 compatibility mode is true , then true ; otherwise either true or error.
|
EBV1 =
false
|
true
|
false
|
error |
error in EBV1 |
if XPath 1.0 compatibility mode is true , then error; otherwise either true or error.
|
error | error |
If XPath 1.0 compatibility mode is true
, the order in which the operands of a logical expression are evaluated is effectively prescribed. Specifically, it is defined that when there is no
need to evaluate the second operand in order to determine the result, then
no error can occur as a result of evaluating the second operand.
If XPath 1.0 compatibility mode is false
, the
order in which the operands of a logical expression are evaluated is
implementation-dependent. In this case,
an or-expression can return true
if the first
expression evaluated is true, and it can raise an error if evaluation
of the first expression raises an error. Similarly, an and-expression
can return false
if the first expression evaluated is
false, and it can raise an error if evaluation of the first expression
raises an error. As a result of these rules, a logical expression is
not deterministic in the presence of errors, as illustrated in the examples
below.
Here are some examples of logical expressions:
The following expressions return
true
:
1 eq 1 and 2 eq 2
1 eq 1 or 2 eq 3
The following
expression may return either false
or raise a dynamic error
(in XPath 1.0 compatibility mode, the result must be false
):
1 eq 2 and 3 idiv 0 = 1
The
following expression may return either true
or raise a
dynamic error
(in XPath 1.0 compatibility mode, the result must be true
):
1 eq 1 or 3 idiv 0 = 1
The following expression must raise a dynamic error:
1 eq 1 and 3 idiv 0 = 1
In addition to and- and or-expressions, XPath 4.0 provides a
function named fn:not
that takes a general sequence as
parameter and returns a boolean value. The fn:not
function
is defined in [XQuery and XPath Functions and Operators 4.0]. The
fn:not
function reduces its parameter to an effective boolean value. It then returns
true
if the effective boolean value of its parameter is
false
, and false
if the effective boolean
value of its parameter is true
. If an error is
encountered in finding the effective boolean value of its operand,
fn:not
raises the same error.
XPath provides an iteration facility called a for expression. It can be used to iterate over the items of a sequence, or the members of an array. In this section the term collection is used to mean the sequence or array, and the term component is used to refer to the items of the sequence or the members of the array.
[15] | ForExpr |
::= |
SimpleForClause "return" ExprSingle
|
|
[16] | SimpleForClause |
::= | "for" "member"? SimpleForBinding ("," SimpleForBinding)* |
|
[17] | SimpleForBinding |
::= | "$" VarName "in" ExprSingle
|
A for
expression is evaluated as follows:
If the for
expression uses multiple variables, it is first expanded to a set of nested for
expressions, each of which uses only one variable.
For example, the expression
for $x in X, $y in Y return $x + $y
is expanded to
for $x in X return for $y in Y return $x + $y
.
Similarly, the expression
for member $x in X, member $y in Y return $x + $y
is expanded to
for member $x in X return for member $y in Y return $x + $y
.
In a single-variable for
expression,
the variable is called the range variable,
the value of the expression that follows the in
keyword is called the binding collection,
and the expression that follows the return
keyword is called the return expression.
When the member
keyword is absent,
the result of the single-variable for
expression is obtained by evaluating the return
expression once
for each item in the binding collection, with the range variable bound to that item. The resulting sequences
are concatenated (as if by the comma operator) in the order of the items in the binding collection from which they were derived.
When the member
keyword is present,
the value of the binding collection must be a single array.
The result of the single-variable for member
expression is obtained by evaluating the return
expression once
for each member of that array, with the range variable bound to that member. The resulting sequences
are concatenated (as if by the comma operator) in the order of the members of the binding collection from which they were derived.
Note that the result is a sequence, not an array.
The following example illustrates the use of a for
expression in restructuring an input document. The example is based on the following
input:
<bib> <book> <title>TCP/IP Illustrated</title> <author>Stevens</author> <publisher>Addison-Wesley</publisher> </book> <book> <title>Advanced Programming in the Unix Environment</title> <author>Stevens</author> <publisher>Addison-Wesley</publisher> </book> <book> <title>Data on the Web</title> <author>Abiteboul</author> <author>Buneman</author> <author>Suciu</author> </book> </bib>
The following example transforms the input document into a list in
which each author's name appears only once, followed by a list of
titles of books written by that author. This example assumes that the
context item is the bib
element in the input
document.
for $a in fn:distinct-values(book/author)
return ((book/author[. = $a])[1], book[author = $a]/title)
The result of the above expression consists of the following
sequence of elements. The titles of books written by a given author
are listed after the name of the author.
The ordering of author
elements in the result is implementation-dependent due to the semantics of the fn:distinct-values
function.
<author>Stevens</author> <title>TCP/IP Illustrated</title> <title>Advanced Programming in the Unix environment</title> <author>Abiteboul</author> <title>Data on the Web</title> <author>Buneman</author> <title>Data on the Web</title> <author>Suciu</author> <title>Data on the Web</title>
The following example illustrates a for
expression containing more than one variable:
for $i in (10, 20),
$j in (1, 2)
return ($i + $j)
The result of the above expression, expressed as a sequence of numbers, is as follows: 11, 12, 21, 22
The scope of a variable bound in a for
expression comprises all subexpressions of the for
expression
that appear after the variable binding. The scope does not
include the expression to which the variable is bound. The following example illustrates how a variable binding may reference another variable bound earlier in the same for
expression:
for $x in $z, $y in f($x)
return g($x, $y)
The following example illustrates processing of an array.
for member $map in parse-json('[{"x":1, "y":2}, {"x":10, "y":20}]') return $map!(?x+?y)
The result is the sequence (3, 30)
.
Note:
The focus for evaluation of the return
clause of a for
expression
is the same as the focus for evaluation of the for
expression itself. The
following example, which attempts to find the total value of a set of
order-items, is therefore incorrect:
fn:sum(for $i in order-item return @price * @qty)
Instead, the expression must be written to use the variable bound in the for
clause:
fn:sum(for $i in order-item return $i/@price * $i/@qty)
XPath allows a variable to be declared and bound to a value using a let expression.
[18] | LetExpr |
::= |
SimpleLetClause "return" ExprSingle
|
|
[19] | SimpleLetClause |
::= | "let" SimpleLetBinding ("," SimpleLetBinding)* |
|
[20] | SimpleLetBinding |
::= | "$" VarName ":=" ExprSingle
|
A let expression is evaluated as follows:
If the let expression uses multiple variables, it is first expanded to a
set of nested let expressions, each of which uses only one variable. For
example, the expression let $x := 4, $y := 3 return $x + $y
is expanded to
let $x := 4 return let $y := 3 return $x + $y
.
In a single-variable let expression, the variable is called the range
variable, the value of the expression that follows the :=
symbol is called
the binding sequence, and the expression that follows the return keyword is
called the return expression. The result of the let expression is obtained
by evaluating the return expression with the range variable bound to the
binding sequence.
The scope of a variable bound in a let expression comprises all subexpressions of the let expression that appear after the variable binding. The scope does not include the expression to which the variable is bound. The following example illustrates how a variable binding may reference another variable bound earlier in the same let expression:
let $x := doc('a.xml')/*, $y := $x//* return $y[@value gt $x/@min]
Most modern programming languages have support for collections of key/value pairs, which may be called maps, dictionaries, associative arrays, hash tables, keyed lists, or objects (these are not the same thing as objects in object-oriented systems). In XPath 4.0, we call these maps. Most modern programming languages also support ordered lists of values, which may be called arrays, vectors, or sequences. In XPath 4.0, we have both sequences and arrays. Unlike sequences, an array is an item, and can appear as an item in a sequence.
Note:
The XPath 4.0 specification focuses on syntax provided for maps and arrays, especially constructors and lookup.
Some of the functionality typically needed for maps and arrays is provided by functions defined in Section 17 Maps and Arrays FO31, including functions used to read JSON to create maps and arrays, serialize maps and arrays to JSON, combine maps to create a new map, remove map entries to create a new map, iterate over the keys of a map, convert an array to create a sequence, combine arrays to form a new array, and iterate over arrays in various ways.
[Definition: A map is a function that associates a set of keys with values, resulting in a collection of key / value pairs.] [Definition: Each key / value pair in a map is called an entry.] [Definition: The value associated with a given key is called the associated value of the key.]
A Map is created using a MapConstructor.
[85] | MapConstructor |
::= | "map" "{" (MapConstructorEntry ("," MapConstructorEntry)*)? "}" |
|
[86] | MapConstructorEntry |
::= |
MapKeyExpr ":" MapValueExpr
|
|
[87] | MapKeyExpr |
::= |
ExprSingle
|
|
[88] | MapValueExpr |
::= |
ExprSingle
|
Note:
In some circumstances, it is necessary to include whitespace before or after the colon of a MapConstructorEntry to ensure that it is parsed as intended.
For instance, consider the expression map{a:b}
.
Although it matches the EBNF for MapConstructor
(with a
matching MapKeyExpr and b
matching MapValueExpr),
the "longest possible match" rule requires that a:b
be parsed as a QName,
which results in a syntax error.
Changing the expression to map{a :b}
or map{a: b}
will prevent this, resulting in the intended parse.
Similarly, consider these three expressions:
map{a:b:c} map{a:*:c} map{*:b:c}
In each case, the expression matches the EBNF in two different ways,
but the "longest possible match" rule forces the parse in which
the MapKeyExpr is a:b
, a:*
, or *:b
(respectively)
and the MapValueExpr is c
.
To achieve the alternative parse
(in which the MapKeyExpr is merely a
or *
),
insert whitespace before and/or after the first colon.
The value of the expression is a map whose entries correspond to the key-value pairs obtained by evaluating the successive MapKeyExpr and MapValueExpr expressions.
Each MapKeyExpr expression is evaluated
and atomized; a
type error
[err:XPTY0004] occurs if the result is
not a single atomic value.
The associated value is the
result of evaluating the corresponding
MapValueExpr.
If the MapValueExpr evaluates to a node, the
associated value is the node itself, not a new node with the same
values.
[Definition: Two atomic values K1
and
K2
have the same key value if
op:same-key(K1, K2)
returns true
, as specified in Section
17.1.1 op:same-key
FO31
]
If two or more entries have the same key value then a dynamic
error is raised [err:XQDY0137].
Example:
The following expression constructs a map with seven entries:
map { "Su" : "Sunday", "Mo" : "Monday", "Tu" : "Tuesday", "We" : "Wednesday", "Th" : "Thursday", "Fr" : "Friday", "Sa" : "Saturday" }
Maps can nest, and can contain any XDM value. Here is an example of a nested map with values that can be string values, numeric values, or arrays:
Maps are function items, and
a dynamic function call can be used to look up
the value associated with a key in a map.
If $map
is a map and $key
is a key,
then $map($key)
is equivalent to map:get($map, $key)
.
The semantics of such a function call are formally defined in
Section
17.1.6 map:get
FO31.
Examples:
$weekdays("Su")
returns the associated value of the key Su
.
$books("Green Eggs and Ham")
returns associated value of the key Green Eggs and Ham
.
Note:
XPath 4.0 also provides an alternate syntax for map and array lookup that is more terse, supports wildcards, and allows lookup to iterate over a sequence of maps or arrays. See 4.14.3 The Lookup Operator ("?") for Maps and Arrays for details.
Map lookups can be chained.
Examples: (These examples assume that $b
is bound to the books map from the previous section)
The expression $b("book")("title")
returns the string Data on the Web
.
The expression $b("book")("author")
returns the array of authors.
The expression $b("book")("author")(1)("last")
returns the string Abiteboul
.
(This example combines 4.14.2.2 Array Lookup using Function Call Syntax with map lookups.)
[Definition: An array is a function item that associates a set of positions, represented as positive integer keys, with values.] The first position in an array is associated with the integer 1. [Definition: The values of an array are called its members.] In the type hierarchy, array has a distinct type, which is derived from function. Atomization converts arrays to sequences (see Atomization).
An array is created using an ArrayConstructor.
[89] | ArrayConstructor |
::= |
SquareArrayConstructor | CurlyArrayConstructor
|
|
[90] | SquareArrayConstructor |
::= | "[" (ExprSingle ("," ExprSingle)*)? "]" |
|
[91] | CurlyArrayConstructor |
::= | "array" EnclosedExpr
|
If a member of an array is a node, its node identity is preserved. In both forms of an ArrayConstructor, if a member expression evaluates to a node, the associated value is the node itself, not a new node with the same values. If the member expression evaluates to a map or array, the associated value is a new map or array with the same values.
A SquareArrayConstructor consists of a comma-delimited set of argument expressions. It returns an array in which each member contains the value of the corresponding argument expression.
Examples:
[ 1, 2, 5, 7 ]
creates an array with four members: 1
, 2
, 5
, and 7
.
[ (), (27, 17, 0)]
creates an array with two members: ()
and the sequence (27, 17, 0)
.
[ $x, local:items(), <tautology>It is what it is.</tautology> ]
creates an array with three members: the value of $x, the result of evaluating the function call, and a tautology element.
A CurlyArrayConstructor can use any expression to create its members. It evaluates its operand expression to obtain a sequence of items and creates an array with these items as members. Unlike a SquareArrayConstructor, a comma in a CurlyArrayConstructor is the comma operator, not a delimiter.
Examples:
array { $x }
creates an array with one member for each item in the sequence to which $x is bound.
array { local:items() }
creates an array with one member for each item in the sequence to which local:items()
evaluates.
array { 1, 2, 5, 7 }
creates an array with four members: 1
, 2
, 5
, and 7
.
array { (), (27, 17, 0) }
creates an array with three members: 27
, 17
, and 0
.
array{ $x, local:items(), <tautology>It is what it is.</tautology> }
creates an array with the following members: the items to which $x
is bound, followed by the items to which local:items()
evaluates, followed by a tautology element.
Note:
XPath 4.0 does not provide explicit support for sparse arrays. Use integer-valued maps to represent sparse arrays, e.g. map { 27 : -1, 153 : 17 }
.
Arrays are function items,
and a dynamic function call can be used to look up
the value associated with position in an array.
If $array
is an array and $index
is an integer corresponding to a position in the array,
then $array($key)
is equivalent to array:get($array, $key)
.
The semantics of such a function call are formally defined in
Section
17.3.2 array:get
FO31.
Examples:
[ 1, 2, 5, 7 ](4)
evaluates to 7
.
[ [1, 2, 3], [4, 5, 6]](2)
evaluates to [4, 5, 6]
.
[ [1, 2, 3], [4, 5, 6]](2)(2)
evaluates to 5
.
[ 'a', 123, <name>Robert Johnson</name> ](3)
evaluates to <name>Robert Johnson</name>
.
array { (), (27, 17, 0) }(1)
evaluates to 27
.
array { (), (27, 17, 0) }(2)
evaluates to 17
.
array { "licorice", "ginger" }(20)
raises a dynamic error [err:FOAY0001]FO31.
Note:
XPath 4.0 also provides an alternate syntax for map and array lookup that is more terse, supports wildcards, and allows lookup to iterate over a sequence of maps or arrays. See 4.14.3 The Lookup Operator ("?") for Maps and Arrays for details.
XPath 4.0 provides a lookup operator for maps and arrays that is more convenient for some common cases. It provides a terse syntax for simple strings as keys in maps or integers as keys in arrays, supports wildcards, and iterates over sequences of maps and arrays.
[92] | UnaryLookup |
::= | "?" KeySpecifier
|
|
[69] | KeySpecifier |
::= |
NCName | IntegerLiteral | StringLiteral | VarRef | ParenthesizedExpr | "*" |
Unary lookup is used in predicates (e.g. $map[?name='Mike']
or with the simple map operator (e.g. $maps ! ?name='Mike'
). See 4.14.3.2 Postfix Lookup for the postfix lookup operator.
UnaryLookup returns a sequence of values selected from the context item, which must be a map or array. If the context item is not a map or an array, a type error is raised [err:XPTY0004].
If the context item is a map:
If the KeySpecifier is an NCName
or a StringLiteral
,
the UnaryLookup operator is equivalent to
.(KS)
, where KS
is the value of the NCName
or StringLiteral
.
If the KeySpecifier is an IntegerLiteral, the UnaryLookup operator is equivalent to .(KS)
, where KS
is the value of the IntegerLiteral.
If the KeySpecifier is a ParenthesizedExpr
or a VarRef
the UnaryLookup operator is equivalent to the following expression, where KS
is the value of the ParenthesizedExpr
or VarRef
:
for $k in fn:data(KS) return .($k)
If the KeySpecifier is a wildcard ("*
"), the UnaryLookup operator is equivalent to the following expression:
for $k in map:keys(.) return .($k)
Note:
The order of keys in map:keys() is implementation-dependent, so the order of values in the result sequence is also implementation-dependent.
If the context item is an array:
If the KeySpecifier is an IntegerLiteral, the UnaryLookup operator is equivalent to .(KS)
, where KS
is the value of the IntegerLiteral.
If the KeySpecifier is an NCName
or StringLiteral
,
the UnaryLookup operator raises a type error [err:XPTY0004].
If the KeySpecifier is a ParenthesizedExpr
or a VarRef
, the UnaryLookup operator is equivalent to the following expression, where KS
is the value of the ParenthesizedExpr
or VarRef
:
for $k in fn:data(KS) return .($k)
If the KeySpecifier is a wildcard ("*
"), the UnaryLookup operator is equivalent to the following expression:
for $k in 1 to array:size(.) return .($k)
Note:
Note that array items are returned in order.
Examples:
?name
is equivalent to .("name")
, an appropriate lookup for a map.
?2
is equivalent to .(2)
, an appropriate lookup for an array or an integer-valued map.
?"first name"
is equivalent to .("first name")
?($a)
and ?$a
are
equivalent to for $k in $a return .($k)
, allowing keys for an array or map to be passed using a variable.
?(2 to 4)
is equivalent to for $k in (2,3,4) return .($k)
, a convenient way to return a range of values from an array.
?(3.5)
raises a type error if the context item is an array because the parameter must be an integer.
([1,2,3], [1,2,5], [1,2])[?3 = 5]
raises an error because ?3
on one of the
items in the sequence fails.
If $m
is bound to the weekdays map described in 4.14.1 Maps, then $m?*
returns the values ("Sunday","Monday","Tuesday","Wednesday", "Thursday", "Friday","Saturday")
, in implementation-dependent order.
[1, 2, 5, 7]?*
evaluates to (1, 2, 5, 7)
.
[[1, 2, 3], [4, 5, 6]]?*
evaluates to ([1, 2, 3], [4, 5, 6])
[68] | Lookup |
::= | "?" KeySpecifier
|
The semantics of a Postfix Lookup expression depend on the form of the KeySpecifier, as follows:
If the KeySpecifier
is an NCName
, StringLiteral
, VarRef
, IntegerLiteral
,
or Wildcard
("*
"), then the expression E?S
is
equivalent to E!?S
. (That is, the semantics of the postfix lookup operator
are defined in terms of the unary lookup operator).
If the KeySpecifier
is a ParenthesizedExpr
, then the expression E?(S)
is equivalent to
for $e in E, $s in fn:data(S) return $e($s)
Note:
The focus for evaluating S
is the same as the focus for the Lookup
expression itself.
Examples:
map { "first" : "Jenna", "last" : "Scott" }?first
evaluates to "Jenna"
map { "first name" : "Jenna", "last name" : "Scott" }?"first name"
evaluates to "Jenna"
[4, 5, 6]?2
evaluates to 5
.
(map {"first": "Tom"}, map {"first": "Dick"}, map {"first": "Harry"})?first
evaluates to the sequence ("Tom", "Dick", "Harry")
.
([1,2,3], [4,5,6])?2
evaluates to the sequence (2, 5)
.
["a","b"]?3
raises a dynamic error [err:FOAY0001]FO31
XPath 4.0 provides a conditional expression based on the keywords if
, then
, and else
.
In addition, it provides a more concise syntax as a ternary expression using the operators ??
and !!
[23] | IfExpr |
::= | "if" "(" Expr ")" "then" ExprSingle "else" ExprSingle
|
|
[14] | TernaryConditionalExpr |
::= |
OrExpr ("??" TernaryConditionalExpr "!!" TernaryConditionalExpr)? |
Both constructs have the same semantics. There are three expressions, called the test expression, the then-expression, and the the else-expression.
With the keyword syntax, the format is:
if (test-expression) then then-expression else else-expression
With the ternary operator syntax, the format is:
test-expression ?? then-expression !! else-expression
Note:
The ternary operator syntax is borrowed from Perl6.
The first step in processing a conditional expression is to find the effective boolean value of the test expression, as defined in 2.5.3 Effective Boolean Value.
The value of a conditional expression is defined as follows: If the
effective boolean value of the test expression is true
, the value of the then-expression is returned. If the
effective boolean value of the test expression is false
,
the value of the else-expression is returned.
Conditional expressions have a special rule for propagating dynamic errors: the then
and else
expressions are
guarded, as described in 2.4.5 Guarded Expressions, to prevent
spurious dynamic errors.
Here are some examples of conditional expressions:
In this example, the test expression is a comparison expression:
if ($widget1/unit-cost < $widget2/unit-cost) then $widget1 else $widget2
In this example, the test expression tests for the existence of an attribute
named discounted
, independently of its value:
if ($part/@discounted) then $part/wholesale else $part/retail
The above example can instead be written:
$part/(@discounted ?? wholesale !! retail)
(Note: the equivalence holds only if $part
is a single item.)
[31] | OtherwiseExpr |
::= |
UnionExpr ( "otherwise" UnionExpr )* |
The otherwise
expression returns the value of its first operand, unless this is an empty
sequence, in which case it returns the value of its second operand.
For example, @price - (@discount otherwise 0)
returns the value of @price - @discount
,
if the attribute @discount
exists, or the value of @price
if the @discount
attribute is absent.
To prevent spurious errors, the right hand operand is guarded: it cannot throw any dynamic error unless the left-hand operand returns an empty sequence.
Note:
The operator is associative (even under error conditions): A otherwise (B otherwise C)
returns
the same result as (A otherwise B) otherwise C
.
Quantified expressions support existential and universal quantification. The
value of a quantified expression is always true
or false
.
[21] | QuantifiedExpr |
::= | ("some" | "every") QuantifierBinding ("," QuantifierBinding)* "satisfies" ExprSingle
|
|
[22] | QuantifierBinding |
::= | "$" VarName "in" ExprSingle
|
A quantified expression begins with
a quantifier, which is the keyword some
or every
, followed by one or more in-clauses that are used to bind variables,
followed by the keyword satisfies
and a test expression. Each in-clause associates a variable with an
expression that returns a sequence of items, called the binding sequence for that variable.
The value of the quantified expression is defined by the following rules:
If the QuantifiedExpr contains
more than one QuantifierBinding, then it is equivalent
to the expression obtained by replacing each comma with satisfies some
or satisfies every
respectively. For example, the expression some $x in X, $y in Y satisfies $x = $y
is equivalent to some $x in X satisfies some $y in Y satisfies $x = $y
,
while the expression every $x in X, $y in Y satisfies $x lt $y
is equivalent to
every $x in X satisfies every $y in Y satisfies $x lt $y
If the quantifier is some
, the QuantifiedExpr returns true
if at least one evaluation of the test expression has the effective boolean value
true
; otherwise it returns false
. In consequence, if the binding sequence is empty,
the result of the QuantifiedExpr is false
.
If the quantifier is every
, the QuantifiedExpr returns true
if every evaluation of the test expression has the effective boolean value
true
; otherwise it returns false
. In consequence, if the binding sequence is empty,
the result of the QuantifiedExpr is true
.
The scope of a variable bound in a quantified expression comprises all subexpressions of the quantified expression that appear after the variable binding. The scope does not include the expression to which the variable is bound.
The order in which test expressions are evaluated for the various binding
tuples is implementation-dependent. If the quantifier
is some
, an implementation may
return true
as soon as it finds one binding tuple for which the test expression has
an effective boolean value of true
, and it may raise a dynamic error as soon as it finds one binding tuple for
which the test expression raises an error. Similarly, if the quantifier is every
, an implementation may return false
as soon as it finds one binding tuple for which the test expression has
an effective boolean value of false
, and it may raise a dynamic error as soon as it finds one binding tuple for
which the test expression raises an error. As a result of these rules, the
value of a quantified expression is not deterministic in the presence of
errors, as illustrated in the examples below.
Here are some examples of quantified expressions:
This expression is true
if every part
element has a discounted
attribute (regardless of the values of these attributes):
every $part in /parts/part satisfies $part/@discounted
This expression is true
if at least
one employee
element satisfies the given comparison expression:
some $emp in /emps/employee satisfies ($emp/bonus > 0.25 * $emp/salary)
This expression is true
if at every
employee
element has at least one salary
child with the attribute current="true"
:
every $emp in /emps/employee satisfies some $sal in $emp/salary satisfies $sal/@current='true'
Note:
Like many quantified expressions, this can be simplified. This example can be written
every $emp in /emps/employee satisfies $emp/salary[@current='true']
, or even
more concisely as empty(/emps/employee[not(salary/@current='true')]
.
Another alternative in XPath 4.0 4.0 is to use the higher-order functions fn:some
and fn:all
.
This example can be written fn:all(/emps/employee, ->(){salary/@current='true'})
In the following examples, each quantified expression evaluates its test
expression over nine pairs of variable bindings, formed from the Cartesian
product of the sequences (1, 2, 3)
and (2, 3, 4)
.
The expression beginning with some
evaluates to true
,
and the expression beginning with every
evaluates to false
.
some $x in (1, 2, 3), $y in (2, 3, 4) satisfies $x + $y = 4
every $x in (1, 2, 3), $y in (2, 3, 4) satisfies $x + $y = 4
This quantified expression may either return true
or raise a type error, since its test expression returns true
for one variable binding
and raises a type error for another:
some $x in (1, 2, "cat") satisfies $x * 2 = 4
This quantified expression may either return false
or raise a type error, since its test expression returns false
for one variable binding and raises a type error for another:
every $x in (1, 2, "cat") satisfies $x * 2 = 4
The instance
of
, cast
, castable
,
and treat
expressions are used to test whether a value
conforms to a given type or to convert it to an instance of a given
type.
[34] | InstanceofExpr |
::= |
TreatExpr ( "instance" "of" SequenceType )? |
The boolean
operator instance of
returns true
if the value of its first operand matches
the SequenceType in its second
operand, according to the rules for SequenceType
matching; otherwise it returns false
. For example:
5 instance of xs:integer
This example returns true
because the given value is an instance of the given type.
5 instance of xs:decimal
This example returns true
because the given value is an integer literal, and xs:integer
is derived by restriction from xs:decimal
.
(5, 6) instance of xs:integer+
This example returns true
because the given sequence contains two integers, and is a valid instance of the specified type.
. instance of element()
This example returns true
if the context item is an element node or false
if the context item is defined but is not an element node.
If the context item is absentDM31, a dynamic error is raised [err:XPDY0002].
[37] | CastExpr |
::= |
ArrowExpr ( "cast" "as" SingleType )? |
|
[93] | SingleType |
::= |
SimpleTypeName "?"? |
|
[115] | SimpleTypeName |
::= |
TypeName | LocalUnionType
|
|
[116] | TypeName |
::= |
EQName
|
|
[128] | LocalUnionType |
::= | "union" "(" ItemType ("," ItemType)* ")" |
Sometimes
it is necessary to convert a value to a specific datatype. For this
purpose, XPath 4.0 provides a cast
expression that
creates a new value of a specific type based on an existing value. A
cast
expression takes two operands: an input
expression and a target type. The type of the
atomized value of the input expression is called the input type.
The target type must be either of:
The name of a type defined in the in-scope schema types,
which must be a simple type [err:XQST0052].
In addition, the target type cannot be xs:NOTATION
, xs:anySimpleType
,
or xs:anyAtomicType
A LocalUnionType
such as union(xs:date, xs:dateTime)
.
[err:XPST0080]. The optional occurrence indicator "?
" denotes that an empty
sequence is permitted. If the target type is a lexical QName that has no namespace prefix, it
is considered to be in the default type
namespace.
Casting a node to xs:QName
can cause surprises because it uses the static context of the cast expression to provide the namespace bindings for this operation.
Instead of casting to xs:QName
, it is generally preferable to use the fn:QName
function, which allows the namespace context to be taken from the document containing the QName.
The semantics of the cast
expression
are as follows:
The input expression is evaluated.
The result of the first step is atomized.
If the result of atomization is a sequence of more than one atomic value, a type error is raised [err:XPTY0004].
If the result of atomization is an empty sequence:
If
?
is specified after the target type, the result of the
cast
expression is an empty sequence.
If ?
is not specified after the target type, a type error is raised [err:XPTY0004].
If the result of atomization is a single atomic value, the result of the cast expression is determined by casting to the target type as described in Section 19 Casting FO31. When casting, an implementation may need to determine whether one type is derived by restriction from another. An implementation can determine this either by examining the in-scope schema definitions or by using an alternative, implementation-dependent mechanism such as a data dictionary. The result of a cast expression is one of the following:
A value of the target type (or, in the case of list types, a sequence of values that are instances of the item type of the list type).
A type error, if casting from the source type to the target type is not supported (for example attempting to convert an integer to a date).
A dynamic error, if the particular input value cannot be
converted to the target type (for example, attempting to convert
the string "three"
to an integer).
[36] | CastableExpr |
::= |
CastExpr ( "castable" "as" SingleType )? |
|
[93] | SingleType |
::= |
SimpleTypeName "?"? |
|
[128] | LocalUnionType |
::= | "union" "(" ItemType ("," ItemType)* ")" |
|
[115] | SimpleTypeName |
::= |
TypeName | LocalUnionType
|
|
[116] | TypeName |
::= |
EQName
|
|
[128] | LocalUnionType |
::= | "union" "(" ItemType ("," ItemType)* ")" |
XPath 4.0 provides an expression that tests whether a given value is castable into a given target type. The target type must be either of:
The name of a type defined in the in-scope schema types,
which must be a simple type [err:XQST0052].
In addition, the target type cannot be xs:NOTATION
, xs:anySimpleType
,
or xs:anyAtomicType
A LocalUnionType
such as union(xs:date, xs:dateTime)
.
The expression E castable as T
returns true
if the result of evaluating E
can be successfully cast into the target type T
by using a cast
expression;
otherwise it returns false
.
If evaluation of E
fails with a dynamic error or if the value of E
cannot be atomized,
the castable
expression as a whole fails.
The castable
expression can be used as a predicate to
avoid errors at evaluation time.
It can also be used to select an appropriate type for processing of a given value, as illustrated in
the following example:
if ($x castable as hatsize) then $x cast as hatsize else if ($x castable as IQ) then $x cast as IQ else $x cast as xs:string
For every simple type in the in-scope schema types (except xs:NOTATION
and xs:anyAtomicType
, and xs:anySimpleType
, which are not instantiable), a constructor function is implicitly defined. In each case, the name of the constructor function is the same as the name of its target type (including namespace). The signature of the constructor function for a given type depends on the type that is being constructed, and can be found in Section
18 Constructor functions
FO31.
[Definition: The constructor function for a given type is used to convert instances of other simple types into the given type. The semantics of the constructor function call T($arg)
are defined to be equivalent to the expression (($arg) cast as T?)
.]
The following examples illustrate the use of constructor functions:
This
example is equivalent to ("2000-01-01" cast as
xs:date?)
.
xs:date("2000-01-01")
This
example is equivalent to
(($floatvalue * 0.2E-5) cast as xs:decimal?)
.
xs:decimal($floatvalue * 0.2E-5)
This example returns an
xs:dayTimeDuration
value equal to 21 days. It is
equivalent to ("P21D" cast as xs:dayTimeDuration?)
.
xs:dayTimeDuration("P21D")
If
usa:zipcode
is a user-defined atomic type
in the in-scope schema types, then the
following expression is equivalent to the
expression ("12345" cast as
usa:zipcode?)
.
usa:zipcode("12345")
Note:
An instance of an atomic type that is not in a namespace can be constructed by using a URIQualifiedName in either a cast expression or a constructor function call. Examples:
17 cast as Q{}apple
Q{}apple(17)
In either context, using an unqualified NCName might not work: in a cast expression, an unqualified name is resolved using the default type namespace, while an unqualified name in a constructor function call is resolved using the default function namespace which will often be inappropriate.
[35] | TreatExpr |
::= |
CastableExpr ( "treat" "as" SequenceType )? |
XPath 4.0 provides an
expression called treat
that can be used to modify the
static type of its
operand.
Like cast
, the treat
expression takes two operands: an expression and a SequenceType. Unlike
cast
, however, treat
does not change the
dynamic type or value of its operand. Instead, the purpose of
treat
is to ensure that an expression has an expected
dynamic type at evaluation time.
The semantics of
expr1
treat as
type1
are as
follows:
During static analysis:
The
static type of the
treat
expression is
type1
. This enables the
expression to be used as an argument of a function that requires a
parameter of
type1
.
During expression evaluation:
If
expr1
matches
type1
,
using the rules for SequenceType
matching,
the treat
expression returns the value of
expr1
; otherwise, it raises a dynamic error
[err:XPDY0050].
If the value of
expr1
is returned, the identity of any nodes in the value is
preserved. The treat
expression ensures that the value of
its expression operand conforms to the expected type at
run-time.
Example:
$myaddress treat as element(*, USAddress)
The
static type of
$myaddress
may be element(*, Address)
, a
less specific type than element(*, USAddress)
. However,
at run-time, the value of $myaddress
must match the type
element(*, USAddress)
using rules for SequenceType
matching;
otherwise a dynamic error is
raised [err:XPDY0050].
!
)[46] | SimpleMapExpr |
::= |
PathExpr ("!" PathExpr)* |
A mapping expression S!E
evaluates the
expression E
once for every item in the sequence
obtained by evaluating S
. The simple mapping operator
"!
" can be applied to any sequence, regardless of the
types of its items, and it can deliver a mixed sequence of nodes,
atomic values, and functions. Unlike the similar "/
"
operator, it does not sort nodes into document order or eliminate
duplicates.
Each operation E1!E2
is evaluated as follows: Expression E1
is evaluated to a sequence S
. Each item in S
then serves in turn to provide an inner focus (the item as the context item, its position in S
as the context position, the length of S
as the context size) for an evaluation of E2
in the dynamic context. The sequences resulting from all the evaluations of E2
are combined as follows: Every evaluation of E2
returns a (possibly empty) sequence of items. These sequences are concatenated and returned.
The returned sequence preserves the orderings within and among the subsequences generated by the evaluations of E2
.
Simple map operators have functionality similar to 4.6.1.1 Path operator (/). The following table summarizes the differences between these two operators
Operator | Path operator (E1 / E2 ) |
Simple map operator (E1 ! E2 ) |
---|---|---|
E1 | Any sequence of nodes | Any sequence of items |
E2 | Either a sequence of nodes or a sequence of non-node items | A sequence of items |
Additional processing | Duplicate elimination and document ordering | Simple sequence concatenation |
The following examples illustrate the use of simple map operators combined with path expressions.
child::div1 / child::para / string() ! concat("id-", .)
Selects the para
element children of the div1
element children of the context node; that is, the para
element grandchildren of the context node that have div1
parents. It then outputs the strings obtained by prepending "id-"
to each of the string values of these grandchildren.
$emp ! (@first, @middle, @last)
Returns the values of the attributes first
, middle
, and last
for element $emp
, in the order given. (The /
operator here returns the attributes in an unpredictable order.)
$docs ! ( //employee)
Returns all the employees within all the documents identified by the variable docs, in document order within each document, but retaining the order of documents.
avg( //employee / salary ! translate(., '$', '') ! number(.))
Returns the average salary of the employees, having converted the salary to a number by removing any $
sign and then converting to a number. (The second occurrence of !
could not be written as /
because the left-hand operand of /
cannot be an atomic value.)
fn:string-join((1 to $n)!"*")
Returns a string containing $n
asterisks.
$values!(.*.) => fn:sum()
Returns the sum of the squares of a sequence of numbers.
string-join(ancestor::*!name(), '/')
Returns a path containing the names of the ancestors of an element, separated by "/
" characters.
[38] | ArrowExpr |
::= |
UnaryExpr ( (FatArrowTarget | ThinArrowTarget) )* |
|
[41] | FatArrowTarget |
::= | "=>" ((ArrowStaticFunction
ArgumentList) | (ArrowDynamicFunction
PositionalArgumentList)) |
|
[42] | ThinArrowTarget |
::= | "->" ((ArrowStaticFunction
ArgumentList) | (ArrowDynamicFunction
PositionalArgumentList) | EnclosedExpr) |
|
[70] | ArrowStaticFunction |
::= |
EQName
|
|
[71] | ArrowDynamicFunction |
::= |
VarRef | ParenthesizedExpr
|
|
[61] | ArgumentList |
::= | "(" ((PositionalArguments ("," KeywordArguments)?) | KeywordArguments)? ")" |
|
[62] | PositionalArgumentList |
::= | "(" PositionalArguments? ")" |
[Definition: An arrow operator applies a function to the value of an expression, using the value as the first argument to the function.]
The fat arrow operator =>
is defined as follows:
Given a UnaryExpr
U
, an ArrowStaticFunction
F
, and an ArgumentList
(A, B, C...)
, the expression U => F(A, B, C...)
is equivalent to the
expression F(U, A, B, C...)
.
Given a UnaryExpr
U
, an ArrowDynamicFunction
F
, and an PositionalArgumentList
(A, B, C...)
, the expression U => F(A, B, C...)
is equivalent to the
expression F(U, A, B, C...)
.
The thin arrow operator ->
is defined as follows:
If the arrow is followed by an ArrowStaticFunction:
Given a UnaryExpr
U
, an ArrowStaticFunction
F
, and an ArgumentList
(A, B, C...)
, the expression U -> F(A, B, C...)
is equivalent to the
expression (U ! F(., A, B, C...))
.
If the arrow is followed by an ArrowDynamicFunction:
Given a UnaryExpr
U
, an ArrowDynamicFunction
F
, and an PositionalArgumentList
(A, B, C...)
, the expression U -> F(A, B, C...)
is equivalent to the
expression (U ! F(., A, B, C...))
.
If the arrow is followed by an EnclosedExpr:
Given a UnaryExpr
U
, and an EnclosedExpr
{E}
, the expression U -> {E}
is equivalent to the expression
(U) ! (E)
.
For example, the expression $x -> {.+1}
is equivalent to
($x)!(.+1)
.
Note:
The precedence of the !
operator is higher than that
of ->
, so $x -> f() -> {.+1}
is equivalent to
($x -> f()) ! (.+1)
. Using the ->
operator in such a pipeline expression,
in preference to !
, can therefore reduce the need for parentheses.
Note:
The expression $x -> {.+1}
can be considered as an abbreviation
for $x -> (->{.+1})()
: that is, it calls the anonymous function
->{.+1}
once for each item in $x
.
The fat arrow operator thus applies the supplied function to the result of the left-hand operand as a whole, while the thin arrow operator applies the function (or enclosed expression) to each item in the value of the left-hand operand individually. In the case where the result of the left-hand operand is a single item, the two operators have almost the same effect; the only difference is that the thin arrow binds the focus.
This syntax is particularly helpful when applying multiple functions to a value in turn. For example, the following expression invites syntax errors due to misplaced parentheses:
tokenize((normalize-unicode(upper-case($string))),"\s+")
In the following reformulation, it is easier to see that the parentheses are balanced:
$string -> upper-case() -> normalize-unicode() -> tokenize("\s+")
Assuming that $string
is a single string, the above example could
equally be written:
$string => upper-case() => normalize-unicode() => tokenize("\s+")
The difference between the two operators is seen when the left-hand operand evaluates to a sequence:
"The cat sat on the mat" => tokenize() -> concat(".") -> upper-case() => string-join(" ")
which returns "THE. CAT. SAT. ON. THE. MAT."
. The first arrow
could be written either as =>
or ->
because the operand is a singleton; the next two
arrows have to be ->
because the function is applied to each item in the tokenized
sequence individually; the final arrow must be =>
because the string-join
function applies to the sequence as a whole.
Note:
It may be useful to think of this as a map/reduce pipeline. The functions
introduced by ->
are mapping operations; the function introduced by =>
is a reduce operation.
The following example introduces an enclosed expression to the pipeline:
(1 to 5) -> xs:double() -> math:sqrt() -> {.+1} => sum()
This is equivalent to sum((1 to 5) ! (math:sqrt(xs:double(.))+1))
.
Note:
The ArgumentList
may include PlaceHolders
,
though this is not especially useful. For example, the expression "$" -> concat(?)
is equivalent
to concat("$", ?)
: its value is a function that prepends a supplied string with
a "$" symbol.
Note:
The ArgumentList
may include keyword arguments if the
function is identified statically (that is, by name). For example,
the following is valid: $xml => xml-to-json(indent:=true()) => parse-json(escape:=false())
.