Please check the errata for any errors or issues reported since publication.
See also translations.
This document is also available in these non-normative formats: XML.
Copyright © 2000 W3C® (MIT, ERCIM, Keio, Beihang). W3C liability, trademark and document use rules apply.
XML is a versatile markup language, capable of labeling the information content of diverse data sources, including structured and semi-structured documents, relational databases, and object repositories. A query language that uses the structure of XML intelligently can express queries across all these kinds of data, whether physically stored in XML or viewed as XML via middleware. This specification describes a query language called XQuery, which is designed to be broadly applicable across many types of XML data sources.
A list of changes made since XQuery 3.1 can be found in J Change Log.
This is a draft prepared by the QT4CG (officially registered in W3C as the XSLT Extensions Community Group). Comments are invited.
The publications of this community group are dedicated to our co-chair, Michael Sperberg-McQueen (1954–2024).
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 XQuery 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 XQuery 4.0 Grammar].
[Definition: A query consists of one or more modules.] If a query is executable, one of its modules has a Query Body containing an expression whose value is the result of the query. An expression is represented in the XQuery grammar by the symbol Expr.
Expr | ::= | (ExprSingle ++ ",") |
ExprSingle | ::= | FLWORExpr |
ExprSingle | ::= | FLWORExpr |
FLWORExpr | ::= | InitialClauseIntermediateClause* ReturnClause |
QuantifiedExpr | ::= | ("some" | "every") (QuantifierBinding ++ ",") "satisfies" ExprSingle |
SwitchExpr | ::= | "switch" SwitchComparand (SwitchCases | BracedSwitchCases) |
TypeswitchExpr | ::= | "typeswitch" "(" Expr ")" (TypeswitchCases | BracedTypeswitchCases) |
IfExpr | ::= | "if" "(" Expr ")" (UnbracedActions | BracedAction) |
TryCatchExpr | ::= | TryClause ((CatchClause+ FinallyClause?) | FinallyClause) |
OrExpr | ::= | AndExpr ("or" AndExpr)* |
The XQuery 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 a ExprSingle, because commas are used to separate the arguments of a function call.
After the comma, the expressions that have next lowest precedence are FLWORExpr,QuantifiedExpr, SwitchExpr, TypeswitchExpr, IfExpr, TryCatchExpr, and OrExpr. Each of these expressions is described in a separate section of this document.
XQuery provides a versatile expression called a FLWOR expression that may contain multiple clauses. The FLWOR expression can be used for many purposes, including iterating over sequences, joining multiple documents, and performing grouping and aggregation. The name FLWOR, pronounced "flower", is suggested by the keywords for, let, where, order by, and return, which introduce some of the clauses used in FLWOR expressions (but this is not a complete list of such clauses.)
The overall syntax of a FLWOR expression is shown here, and relevant parts of the syntax are expanded in subsequent sections.
FLWORExpr | ::= | InitialClauseIntermediateClause* ReturnClause |
InitialClause | ::= | ForClause | LetClause | WindowClause |
ForClause | ::= | "for" (ForBinding ++ ",") |
LetClause | ::= | "let" (LetBinding ++ ",") |
WindowClause | ::= | "for" (TumblingWindowClause | SlidingWindowClause) |
IntermediateClause | ::= | InitialClause | WhereClause | WhileClause | GroupByClause | OrderByClause | CountClause |
WhereClause | ::= | "where" ExprSingle |
WhileClause | ::= | "while" ExprSingle |
GroupByClause | ::= | "group" "by" (GroupingSpec ++ ",") |
OrderByClause | ::= | "stable"? "order" "by" (OrderSpec ++ ",") |
CountClause | ::= | "count" VarName |
ReturnClause | ::= | "return" ExprSingle |
The semantics of FLWOR expressions are based on a concept called a tuple stream. [Definition: A tuple stream is an ordered sequence of zero or more tuples.] [Definition: A tuple is a set of zero or more named variables, each of which is bound to a value that is an XDM instance.] Each tuple stream is homogeneous in the sense that all its tuples contain variables with the same names and the same static types. The following example illustrates a tuple stream consisting of four tuples, each containing three variables named $x, $y, and $z:
($x = 1003, $y = "Fred", $z = <age>21</age>) ($x = 1017, $y = "Mary", $z = <age>35</age>) ($x = 1020, $y = "Bill", $z = <age>18</age>) ($x = 1024, $y = "John", $z = <age>29</age>)
Note:
In this section, tuple streams are represented as shown in the above example. Each tuple is on a separate line and is enclosed in parentheses, and the variable bindings inside each tuple are separated by commas. This notation does not represent XQuery syntax, but is simply a representation of a tuple stream for the purpose of defining the semantics of FLWOR expressions.
Tuples and tuple streams are not part of the data model. They exist only as conceptual intermediate results during the processing of a FLWOR expression.
Conceptually, the first clause generates a tuple stream. Each clause between the first clause and the return clause takes the tuple stream generated by the previous clause as input and generates a (possibly different) tuple stream as output. The return clause takes a tuple stream as input and, for each tuple in this tuple stream, generates an XDM instance; the final result of the FLWOR expression is the ordered concatenation of these XDM instances.
The initial clause in a FLWOR expression may be a for, let, or window clause. Intermediate clauses may be for, let, window, count, where, group by, or order by clauses. These intermediate clauses may be repeated as many times as desired, in any order. The final clause of the FLWOR expression must be a return clause. The semantics of the various clauses are described in the following sections.
A for member clause is added to FLWOR expressions to allow iteration over an array. [Issue 49 PR 344 10 February 2023]
A for key/value clause is added to FLWOR expressions to allow iteration over a map. [Issue 31 PR 1249 1 June 2024]
The value bound to a variable in a for clause is now converted to the declared type by applying the coercion rules. [Issue 189 PR 820 8 November 2023]
ForClause | ::= | "for" (ForBinding ++ ",") |
ForBinding | ::= | ForItemBinding | ForMemberBinding | ForEntryBinding |
ForItemBinding | ::= | VarNameAndTypeAllowingEmpty? PositionalVar? "in" ExprSingle |
VarNameAndType | ::= | "$" EQNameTypeDeclaration? |
EQName | ::= | QName | URIQualifiedName |
TypeDeclaration | ::= | "as" SequenceType |
SequenceType | ::= | ("empty-sequence" "(" ")") |
AllowingEmpty | ::= | "allowing" "empty" |
PositionalVar | ::= | "at" VarName |
VarName | ::= | "$" EQName |
ExprSingle | ::= | FLWORExpr |
ForMemberBinding | ::= | "member" VarNameAndTypePositionalVar? "in" ExprSingle |
ForEntryBinding | ::= | ((ForEntryKeyBindingForEntryValueBinding?) | ForEntryValueBinding) PositionalVar? "in" ExprSingle |
ForEntryKeyBinding | ::= | "key" VarNameAndType |
ForEntryValueBinding | ::= | "value" VarNameAndType |
A for clause is used for iteration. Each variable in a for clause iterates over a sequence, an array, or a map.
The expression following the keyword in is evaluated; we refer to the resulting sequence, array, or map generically as the binding collection, and to its items, members, or entries as the components of the collection.
When a ForItemBinding is used (that is, when none of the keywords member, key, or value is used), the range variable is bound in turn to each item in the binding collection, which is treated as a sequence of items.
When a ForMemberBinding is used (that is, when the keyword member is used), the range variable is bound in turn to each member of the array.
In this case the corresponding ExprSingle must evaluate to a single array, otherwise a type error is raised [err:XPTY0141]. However, the coercion rules also allow a JNode whose ·content· is an array to be supplied.
When a ForEntryBinding is used (that is, when either or both of the keywords key and value are used), the key range variable (if present) is bound in turn to each key in the map (in entry orderDM), and the value range variable (if present) is bound to the corresponding value.
In this case the corresponding ExprSingle must evaluate to a single map, otherwise a type error is raised [err:XPTY0141]. However, the coercion rules also allow a JNode whose ·content· is a map to be supplied.
If both the key and value variables are declared, their expanded QNames must be distinct [err:XQST0089].
If a for clause contains multiple bindings separated by commas it is semantically equivalent to multiple for clauses, each containing one of the bindings in the original for clause.
Example:
The clause
for $x in $expr1, $y in $expr2
is semantically equivalent to:
for $x in $expr1 for $y in $expr2
The clause
for member $x in $expr1, member $y in $expr2
is semantically equivalent to:
for member $x in $expr1 for member $y in $expr2
In the remainder of this section, we define the semantics of a for clause containing a single variable and an associated expression (following the keyword in) whose value is the binding collection for that variable.
If a single-variable for clause is the initial clause in a FLWOR expression, it iterates over its binding collection, binding the variable(s) to each component in turn. The resulting sequence of variable bindings becomes the initial tuple stream that serves as input to the next clause of the FLWOR expression. The order of tuples in the tuple stream preserves the order of the binding collection.
If the binding collection is empty, the output tuple stream depends on whether allowing empty is specified. If allowing empty is specified, the output tuple stream consists of one tuple in which the variable is bound to an empty sequence. This option is not available when the keywords member, key, or value are used. If allowing empty is not specified, the output tuple stream consists of zero tuples.
The following examples illustrates tuple streams that are generated by initial for clauses:
Initial clause:
for $x in (100, 200, 300)
or (equivalently):
for $x allowing empty in (100, 200, 300)
Output tuple stream:
($x = 100) ($x = 200) ($x = 300)
Initial clause:
for $x in ()
Output tuple stream contains no tuples.
Initial clause:
for $x allowing empty in ()
Output tuple stream:
($x = ())
Initial clause:
for member $x in [ 1, 2, (5 to 10) ]
Output tuple stream:
($x = (1)) ($x = (2)) ($x = (5, 6, 7, 8, 9, 10)
Initial clause:
for member $x in []
Output tuple stream contains no tuples.
Initial clause:
for key $k value $v in { 'x': 1, 'y': 2 }Output tuple stream:
($k = 'x', $v = 1) ($k = 'y', $v = 2)
[Definition: A positional variable is a variable that is preceded by the keyword at.] A positional variable may be associated with the range variable(s) that are bound in a for clause. In this case, as the main range variable(s) iterate over the components of its binding collection, the positional variable iterates over the integers that represent the ordinal numbers of these component in the binding collection, starting with one. Each tuple in the output tuple stream contains bindings for both the main variable and the positional variable. If the binding collection is empty and allowing empty is specified, the positional variable in the output tuple is bound to the integer zero. Positional variables have the implied type xs:integer.
The expanded QName of a positional variable must be distinct from the expanded QName of the main variable with which it is associated [err:XQST0089].
The following examples illustrate how a positional variable would have affected the results of the previous examples that generated tuples:
Initial clause:
for $x at $i in (100, 200, 300)
Output tuple stream:
($x = 100, $i = 1) ($x = 200, $i = 2) ($x = 300, $i = 3)
Initial clause:
for $x at $i in [1 to 3, 11 to 13, 21 to 23
Output tuple stream:
($x = (1, 2, 3), $i = 1) ($x = (11, 12, 13), $i = 2) ($x = (21, 22, 23), $i = 3)
Initial clause:
for $x allowing empty at $i in ()
Output tuple stream:
($x = (), $i = 0)
If a single-variable for clause is an intermediate clause in a FLWOR expression, its binding collection is evaluated for each input tuple, given the bindings in that input tuple. Each input tuple generates zero or more tuples in the output tuple stream. Each of these output tuples consists of the original variable bindings of the input tuple plus a binding of the new variable to one of the items in its binding collecction.
Note:
Although the binding collection is conceptually evaluated independently for each input tuple, an optimized implementation may sometimes be able to avoid re-evaluating the binding collection if it can show that the variables that the binding collection depends on have the same values as in a previous evaluation.
For a given input tuple, if the binding collection for the new variable in the for clause is empty (that is, it is an empty sequence or an empty arrayDM depending on whether member is specified), and if allowing empty is not specified, the input tuple generates zero output tuples (it is not represented in the output tuple stream.)
The allowing empty option is available only when processing sequences, not when processing arrays or maps. The effect is that if the binding collection is an empty sequence, the input tuple generates one output tuple, with the original variable bindings plus a binding of the new variable to an empty sequence.
Note:
If a type declaration is present and allowing empty is specified, the type declaration should include an occurrence indicator of "?" to indicate that the variable may be bound to an empty sequence.
If the new variable introduced by a for clause has an associated positional variable, the output tuples generated by the for clause also contain bindings for the positional variable. In this case, as the new variable is bound to each item in its binding collection, the positional variable is bound to the ordinal position of that item within the binding collection, starting with one. Note that, since the positional variable represents a position within a binding collection, the output tuples corresponding to each input tuple are independently numbered, starting with one. For a given input tuple, if the binding collection is empty and allowing empty is specified, the positional variable in the output tuple is bound to the integer zero.
The tuples in the output tuple stream are ordered primarily by the order of the input tuples from which they are derived, and secondarily by the order of the binding sequence for the new variable; otherwise the order of the output tuple stream is implementation-dependent.
The following examples illustrates the effects of intermediate for clauses:
Input tuple stream:
($x = 1) ($x = 2) ($x = 3) ($x = 4)
Intermediate for clause:
for $y in ($x to 3)
Output tuple stream:
($x = 1, $y = 1) ($x = 1, $y = 2) ($x = 1, $y = 3) ($x = 2, $y = 2) ($x = 2, $y = 3) ($x = 3, $y = 3)
Note:
In this example, there is no output tuple that corresponds to the input tuple ($x = 4) because, when the for clause is evaluated with the bindings in this input tuple, the resulting binding collection for $y is empty.
This example shows how the previous example would have been affected by a positional variable (assuming the same input tuple stream):
for $y at $j in ($x to 3)
Output tuple stream:
($x = 1, $y = 1, $j = 1) ($x = 1, $y = 2, $j = 2) ($x = 1, $y = 3, $j = 3) ($x = 2, $y = 2, $j = 1) ($x = 2, $y = 3, $j = 2) ($x = 3, $y = 3, $j = 1)
This example shows how the previous example would have been affected by allowing empty. Note that allowing empty causes the input tuple ($x = 4) to be represented in the output tuple stream, even though the binding sequence for $y contains no items for this input tuple. This example illustrates that allowing empty in a for clause serves a purpose similar to that of an “outer join” in a relational database query. (Assume the same input tuple stream as in the previous example.)
for $y allowing empty at $j in ($x to 3)
Output tuple stream:
($x = 1, $y = 1, $j = 1) ($x = 1, $y = 2, $j = 2) ($x = 1, $y = 3, $j = 3) ($x = 2, $y = 2, $j = 1) ($x = 2, $y = 3, $j = 2) ($x = 3, $y = 3, $j = 1) ($x = 4, $y = (), $j = 0)
This example illustrates processing of arrays:
Input tuple stream:
($x = 1) ($x = 2) ($x = 3)
Intermediate for clause:
for member $y in [[$x+1, $x+2], [[$x+3, $x+4]]
Output tuple stream:
($x = 1, $y = [ 2, 3 ]) ($x = 1, $y = [ 4, 5 ]) ($x = 2, $y = [ 3, 4 ]) ($x = 2, $y = [ 5, 6 ]) ($x = 3, $y = [ 4, 5 ]) ($x = 3, $y = [ 6, 7 ])
This example shows how a for clause that binds two variables is semantically equivalent to two for clauses that bind one variable each. We assume that this for clause occurs at the beginning of a FLWOR expression. It is equivalent to an initial single-variable for clause that provides an input tuple stream to an intermediate single-variable for clause.
for $x in (1, 2, 3, 4), $y in ($x to 3)
Output tuple stream:
($x = 1, $y = 1) ($x = 1, $y = 2) ($x = 1, $y = 3) ($x = 2, $y = 2) ($x = 2, $y = 3) ($x = 3, $y = 3)
A for clause may contain one or more type declarations, identified by the keyword as. The semantics of type declarations are defined in 4.13.1 Variable Bindings.
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 XQuery 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 XQuery 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 XQuery 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 18 Processing mapsFO and Section 19 Processing arraysFO, 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.]
Maps and their properties are defined in the data model: see Section 8.2 Map ItemsDM. For an overview of the functions available for processing maps, see Section 18 Processing mapsFO.
Note:
Maps in XQuery 4.0 are ordered. The effect of this property is explained in Section 8.2 Map ItemsDM. In an ordered map, the order of entries is predictable and depends on the order in which they were added to the map.
In map constructors, the keyword map is now optional, so map { 0: false(), 1: true() } can now be written { 0: false(), 1: true() }, provided it is used in a context where this creates no ambiguity. [Issue 1070 PR 1071 26 March 2024]
The order of key-value pairs in the map constructor is now retained in the constructed map. [Issue 1651 PR 1703 14 January 2025]
A general expression is allowed within a map constructor; this facilitates the creation of maps in which the presence or absence of particular keys is decided dynamically. [Issue 2003 PR 2094 13 July 2025]
A map can be created using a MapConstructor.
Examples are:
{ "a": 1, "b": 2 }which constructs a map with two entries, and
{ "a": 1, if ($condition) { map{ "b": 2 } } }which constructs a map having either one or two entries depending on the value of $condition.
Both the keys and the values in a map constructor can be supplied as expressions rather than as constants.
MapConstructor | ::= | "map"? "{" (MapConstructorEntry ** ",") "}" |
MapConstructorEntry | ::= | ExprSingle (":" ExprSingle)? |
ExprSingle | ::= | FLWORExpr |
Note:
The keyword map was required in earlier versions of the language; in XQuery 4.0 it becomes optional. There may be cases where using the keyword improves readability.
In order to allow the map keyword to be omitted, an incompatible change has been made to XQuery computed element and attribute constructors: if the name of the constructed element or attribute is a language keyword, it must now be written using the QNameLiteral syntax, for example element #div {}.
Although the grammar allows a MapConstructor to appear within an EnclosedExpr (that is, between curly brackets), this may be confusing to readers, and using the map keyword in such cases may improve clarity. The keyword map is used in the second example above to avoid any confusion between the braces required for the then part of the conditional expression, and the braces required for the inner map constructor.
If the EnclosedExpr appears in a context such as a StringTemplate, the two adjacent left opening braces must at least be separated by whitespace.
When a MapConstructorEntry is written as two instances of ExprSingle separated by a colon, the first expression is evaluated and atomized to form a key, and the second expression is evaluated to form the corresponding value. The result is a single-entry mapDM which will be merged into the constructed map, as described below. A type error [err:XPTY0004] occurs if the result of the first expression (after atomization) is not a single atomic item. The result of the second expression is used as is.
When the MapConstructorEntry is written as a single instance of ExprSingle with no colon, it must evaluate to a sequence of zero or more map items ([err:XPTY0004]). However, the coercion rules also allow a JNode whose ·content· is a map (or a sequence of maps) to be supplied. These map items will be merged into the constructed map, as described below.
Each contained MapConstructorEntry thus delivers zero or more maps, and the result of the map constructor is a new map obtained by merging these component maps, in order, as if by the map:merge function.
[Definition: Two atomic items K1 and K2 have the same key value if fn:atomic-equal(K1, K2) returns true, as specified in Section 14.2.1 fn:atomic-equalFO ] If two or more entries have the same key value then a dynamic error is raised [err:XQDY0137]. The error may be raised statically if two or more entries can be determined statically to have the same key value.
The entry orderDM of the entries in the constructed map retains the order of the MapConstructorEntry entries in the input.
The following expression constructs a map with seven entries:
The following expression constructs a map with either five or seven entries, depending on a supplied condition:
{
"Mo" : "Monday",
"Tu" : "Tuesday",
"We" : "Wednesday",
"Th" : "Thursday",
"Fr" : "Friday",
if ($include-weekends) {
{ "Sa" : "Saturday",
"Su" : "Sunday"
}
}
}
The following expression (which uses two nested map constructors) constructs a map that indexes employees by the value of their @id attribute:
{ //employee ! {@id, .} }
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:
{
"book": {
"title": "Data on the Web",
"year": 2000,
"author": [
{
"last": "Abiteboul",
"first": "Serge"
},
{
"last": "Buneman",
"first": "Peter"
},
{
"last": "Suciu",
"first": "Dan"
}
],
"publisher": "Morgan Kaufmann Publishers",
"price": 39.95
}
}Note:
The syntax deliberately mimics JSON, but there are a few differences. JSON constructs that are not accepted in XQuery 4.0 map constructors include the keywords true, false, and null, and backslash-escaped characters such as "\n" in string literals. In an XQuery 4.0 map constructor, of course, any literal value can be replaced with an expression.
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 {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 {a :b} or {a: b} will prevent this, resulting in the intended parse.
Similarly, consider these three expressions:
{a:b:c}
{a:*:c}
{*: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.
Note:
There are also several functions that can be used to construct maps with a variable number of entries:
map:build takes any sequence as input, and for each item in the sequence, it computes a key and a value, by calling user-supplied functions.
map:merge takes a sequence of maps (often but not necessarily single-entry mapDM) and merges them into a single map.
map:of-pairs takes a sequence of key-value pair mapsFO and merges them into a single map.
Any of these functions can be used to build an index of employee elements using the value of the @id attribute as a key:
map:build(//employee, fn { @id })
map:merge(//employee ! { @id, . })
map:of-pairs(//employee ! { 'key': @id, 'value': . })
All three functions also provide control over:
The way in which duplicate keys are handled, and
The ordering of entries in the resulting map.
FilterExprAM | ::= | PostfixExpr "?[" Expr "]" |
PostfixExpr | ::= | PrimaryExpr | FilterExpr | DynamicFunctionCall | LookupExpr | FilterExprAM |
Expr | ::= | (ExprSingle ++ ",") |
Maps and arrays can be filtered using the construct INPUT?[FILTER]. For example, $array?[count(.)=1] filters an array to retain only those members that are single items.
Note:
The character-pair ?[ forms a single token; no intervening whitespace or comment is allowed.
The required type of the left-hand operand INPUT is (map(*)|array(*))?: that is, it must be either an empty sequence, a single map, or a single array [err:XPTY0004]. However, the coercion rules also allow a JNode whose ·content·If it is a map or array to be supplied. If the value is an empty sequence, the result of the expression is an empty sequence.
If the value of INPUT is an array, then the FILTER expression is evaluated for each member of the array, with that member as the context value, with its position in the array as the context position, and with the size of the array as the context size. The result of the expression is an array containing those members of the input array for which the predicate truth value of the FILTER expression is true. The order of retained members is preserved.
For example, the following expression:
let $array := [ (), 1, (2, 3), (4, 5, 6) ] return $array?[count(.) ge 2]
returns:
[ (2, 3), (4, 5, 6) ]
Note:
Numeric predicates are handled in the same way as with filter expressions for sequences. However, the result is always an array, even if only one member is selected. For example, given the $array shown above, the result of $array?[3] is the single-member arrayDM[ (2, 3) ]. Contrast this with $array?3 which delivers the sequence 2, 3.
If the value of INPUT is a map, then the FILTER expression is evaluated for each entry in the map, with the context value set to an item of type record(key as xs:anyAtomicType, value as item()*), in which the key and value fields represent the key and value of the map entry. The context position is the position of the entry in the map (in entry orderDM), and the context size is the number of entries in the map. The result of the expression is a map containing those entries of the input map for which the predicate truth value of the FILTER expression is true. The relative order of entries in the result retains the relative order of entries in the input.
For example, the following expression:
let map := { 1: "alpha", 2: "beta", 3: "gamma" }
return $map?[?key ge 2]returns:
{ 2: "beta", 3: "gamma" }Note:
A filter expression such as $map?[last()-1, last()] might be used to return the last two entries of a map in entry orderDM.