View Old View New View Both View Only Previous Next

This draft contains only sections that have differences from the version that it modified.

W3C

XQuery 4.0: An XML Query Language

W3C Editor's Draft 23 February 2026

This version:
https://qt4cg.org/specifications/xquery-40/
Most recent version of XQuery:
https://qt4cg.org/specifications/xquery-40/
Most recent Recommendation of XQuery:
https://www.w3.org/TR/2017/REC-xquery-31-20170321/
Editor:
Michael Kay, Saxonica <mike@saxonica.com>

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.


Abstract

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.

Status of this Document

This is a draft prepared by the QT4CG (officially registered in W3C as the XSLT Extensions Community Group). Comments are invited.

Dedication

The publications of this community group are dedicated to our co-chair, Michael Sperberg-McQueen (1954–2024).


4 Expressions

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
| QuantifiedExpr
| SwitchExpr
| TypeswitchExpr
| IfExpr
| TryCatchExpr
| OrExpr
ExprSingle::=FLWORExpr
| QuantifiedExpr
| SwitchExpr
| TypeswitchExpr
| IfExpr
| TryCatchExpr
| OrExpr
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.

4.4 Filter Expressions

Changes in 4.0  

  1. The value of a predicate in a filter expression can now be a sequence of integers.   [Issue 816 PR 996 6 February 2024]

FilterExpr::=PostfixExprPredicate
PostfixExpr::=PrimaryExpr | FilterExpr | DynamicFunctionCall | LookupExpr | MethodCall | FilterExprAM
Predicate::="[" Expr "]"
Expr::=(ExprSingle ++ ",")

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 an AbbreviatedStep or FullStep, the expression is technically not a filter expression but an AxisStep. There are minor differences in the semantics: see 4.6.5 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[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)[last()]

For each item in the input sequence, the predicate expression is evaluated using an inner focus, defined as follows: The context value 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 value 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.

[Definition: The predicate truth value of a value $V is the result of the expression if ($V instance of xs:numeric+) then ($V = position()) else fn:boolean($V).]

Expanding this definition, the predicate truth value can be obtained by applying the following rules, in order:

  1. If the value V of the predicate expression is a sequence whose first item is an instance of the type xs:numeric, then:

    1. V must be an instance of the type xs:numeric+ (that is, every item in V must be numeric). A type error [err:FORG0006]FO40 is raised if this is not the case.

    2. The predicate truth value is true if V is equal (by the = operator) to the context position, and is false otherwise.

    In effect this means that an item in the input sequence is selected if its position in the sequence is equal to one or more of the numeric values in the predicate. For example, the predicate [3 to 5] is true for the third, fourth, and fifth items in the input sequence.

    [Definition: A predicate whose predicate expression returns a value of type xs:numeric+ is called a numeric predicate.]

    Note:

    It is possible, though not generally useful, for the value of a numeric predicate to depend on the focus, and thus to differ for different items in the input sequence. For example, the predicate [xs:integer(@seq)] selects those items in the input sequence whose @seq attribute is numerically equal to their position in the input sequence.

    It is also possible, and again not generally useful, for the value of the predicate to be numeric for some items in the input sequence, and boolean for others. For example, the predicate [@special otherwise last()] is true for an item that either has an @special attribute, or is the last item in the input sequence.

    Note:

    The truth value of a numeric predicate does not depend on the order of the numbers in V. The predicates [ 1, 2, 3 ] and [ 3, 2, 1 ] have exactly the same effect. The items in the result of a filter expression always retain the ordering of the input sequence.

    Note:

    The truth value of a numeric predicate whose value is non-integral or non-positive is always false.

    Note:

    Beware that using boolean operators (and, or, not()) with numeric values may not have the intended effect. For example the predicate [1 or last()] selects every item in the sequence, because or operates on the effective boolean value of its operands. The required effect can be achieved with the predicate [1, last()].

  2. Otherwise, the predicate truth value is the effective boolean value of the predicate expression.

4.6 Path Expressions

Changes in 4.0  

  1. Path expressions are extended to handle JNodes (found in trees of maps and arrays) as well as XNodes (found in trees representing parsed XML).   [Issue 2054 ]

PathExpr::=AbsolutePathExpr
| RelativePathExpr
/* xgc: leading-lone-slash */
AbsolutePathExpr::=("/" RelativePathExpr?) | ("//" RelativePathExpr)
RelativePathExpr::=StepExpr (("/" | "//") StepExpr)*

[Definition: A path expression is either an absolute path expression or a relative path expression ]

[Definition: An absolute path expression is an instance of the production AbsolutePathExpr: it consists of either (a) the operator / followed by zero or more operands separated by / or // operators, or (b) the operator // followed by one or more operands separated by / or // operators.]

[Definition: A relative path expression is a non-trivial instance of the production RelativePathExpr: it consists of two or more operand expressions separated by / or // operators.]

[Definition: The operands of a path expression are conventionally referred to as steps.]

Note:

The term step must not be confused with axis step. A step can be any kind of expression, often but not necessarily an axis step, while an axis step can be used in any expression context, not necessarily as a step in a path expression.

A path expression is typically used to locate GNodes within GTrees.

Note:

Note the terminology:

The following definitions are copied from the data model specification, for convenience:

  • [Definition: A tree that is rooted at a parentless JNode is referred to as a JTree.]

  • [Definition: A tree that is rooted at a parentless XNode is referred to as an XTree.]

  • [Definition: The term generic node or GNode is a collective term for XNodes (more commonly called simply nodes) representing the parts of an XML document, and JNodes, often used to represent the parts of a JSON document.]

  • [Definition: A JNode is a kind of item used to represent a value within the context of a tree of maps and arrays. A root JNode represents a map or array; a non-root JNode represents a member of an array or an entry in a map.]

[Definition: The term GTree means JTree or XTree.]

Absolute path expressions (those starting with an initial / or //), start their selection from the root GNode of a GTree; relative path expressions (those without a leading / or //) start from the context value.

4.6.1 Absolute Path Expressions

The expression consisting of / on its own is treated as an abbreviation for the path expression/..

An expression of the form /PP (that is, a path expression with a leading /) is treated as an abbreviation for the expression self::gnode()/(fn:root(.) treat as (document-node()|jnode())/PP. The effect of this expansion is that for every item J in the context value V:

  1. A type error occurs if J is not a GNode [err:XPTY0020].

  2. The root GNode R of the GTree containing J is selected.

  3. A type error occurs if R is neither a JNode nor a document node [err:XPDY0050].

  4. The expression that follows the leading / is evaluated with R as the context value.

Note:

If the context value includes a map or array, it is not converted implicitly to a JNode; rather, a type error occurs.

The results of these multiple evaluations are then combined into a single sequence; if the result is a set of GNodes, the GNodes are delivered in document order with duplicates eliminated.

Note:

The / character can be used either as a complete 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 that could be confused with a node test, 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 /*.

An expression of the form //PP (that is, an absolute path expression with a leading //) is treated as an abbreviation for the expression self::gnode()/(fn:root(.) treat as (document-node()|jnode())/descendant-or-self::gnode()/PP. The effect of this expansion is that for every item J in the context value V:

  1. A type error occurs if J is not a GNode [err:XPTY0020].

  2. The root GNode R of the GTree containing J is selected.

  3. A type error occurs if R is neither a JNode nor a document node [err:XPDY0050].

  4. The descendants of R are selected, along with R itself.

  5. For every GNode D in this set of GNodes, the expression that follows the leading // is evaluated with D as the context value.

The results of these multiple evaluations are then combined into a single sequence; if the result is a set of GNodes, the GNodes are delivered in document order with duplicates eliminated.

Any map or array that is present in the context value is first coerced to a JNode by applying the JNodefn:jtree function.

If (after this coercion) the context value is not a sequence of GNodes, a type error is raised [err:XPTY0020]. At evaluation time, if the root GNode of any item in the context value is not a document node or a JNode, a type error is raised [err:XPDY0050].

Note:

The descendants of an XNode do not include attribute nodes. However, the rules for expanding // ensure that .//@* selects all attributes of all descendants

Note:

// on its own is not a valid expression.

4.6.3 Path operator (/)

The path operator / is primarily used for locating GNodes within GTrees. The value of the left-hand operand may include maps and arrays; such items are implicitly converted to JNodes as if by a call on the jnodefn:jtree function. After this conversion, the left-hand operand must return a sequence of GNodes. The result of the operator is either a sequence of GNodes (in document order, with no duplicates), or a sequence of non-GNodes.

The operation E1/E2 is evaluated as follows: Expression E1 is evaluated. Any maps or arrays in the result are converted to JNodes by applying the JNodefn:jtree function. If the result is not a (possibly empty) sequence S of GNodes, a type error is raised [err:XPTY0019]. Each GNode in S then serves in turn to provide an inner focus (the GNode as the context value, 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:

  1. If every evaluation of E2 returns a (possibly empty) sequence of GNodes, these sequences are combined, and duplicate GNodes are eliminated based on GNode identity. The resulting GNode sequence is returned in document order.

  2. If every evaluation of E2 returns a (possibly empty) sequence of non-GNodes, 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.

    Note:

    The use of path expressions to select values other than GNodes is for backwards compatibility. Generally it is preferable to use the simple mapping operator ! for this purpose. For example, write $nodes!node-name() in preference to $nodes/node-name().

  3. If the multiple evaluations of E2 return at least one GNode and at least one non-GNode, 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 (the function fn:distinct-ordered-nodes($R) has the effect of eliminating duplicates and sorting nodes into document order):

let $R := E1 ! E2
return if (every $r in $R satisfies $r instance of gnode())
       then (fn:distinct-ordered-nodes($R))
       else if (every $r in $R satisfies not($r instance of gnode()))
       then $R
       else error()

For a table comparing the step operator to the map operator, see 4.23 Simple map operator (!).

4.6.4 Axis Steps

AxisStep::=(AbbreviatedStep | FullStep) Predicate*
AbbreviatedStep::=".." | ("@" NodeTest) | SimpleNodeTest
FullStep::=AxisNodeTest
Axis::=("ancestor" | "ancestor-or-self" | "attribute" | "child" | "descendant" | "descendant-or-self" | "following" | "following-or-self" | "following-sibling" | "following-sibling-or-self" | "parent" | "preceding" | "preceding-or-self" | "preceding-sibling" | "preceding-sibling-or-self" | "self") "::"
NodeTest::=UnionNodeTest | SimpleNodeTest
Predicate::="[" Expr "]"
Expr::=(ExprSingle ++ ",")

[Definition: An axis step is an instance of the production AxisStep: it is an expression that returns a sequence of GNodes that are reachable from a starting GNode via a specified axis. An axis step has three parts: an axis, which defines the direction of movement for the step, a node test, which selects GNodes based on their properties, and zero or more predicates which are used to filter the results.]

Note:

An axis step is an expression in its own right. While axis steps are often used as the operands of path expressions, they can also appear in other contexts (without a / or // operator); equally, the operands of a path expression can be any expression, not restricted to an axis step.

If the context value for an axis step includes a map or array, this is implicitly converted to a JNode as if by applying the fn:jnodefn:jtree function. If, after this conversion, the sequence contains a value that is not a GNode, a type error is raised [err:XPTY0020]. The result of evaluating the axis step is a sequence of zero or more GNodes.

The axis stepS is equivalent to ./S. Thus, if the context value is a sequence containing multiple GNodes, the semantics of a axis step are equivalent to a path expression in which the step is always applied to a single GNode. The following description therefore explains the semantics for the case where the context value is a single GNode, called the origin.

Note:

The equivalence of a axis stepS to the path expression./S means that the resulting GNode sequence is returned in document order.

In the abbreviated syntax for a step, the axis can be omitted and other shorthand notations can be used as described in 4.6.7 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 GNodes reachable from the origin via the specified axis that match the node test. For example, the step child::para selects the para element children of the origin XNode: 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.4.1 Axes. The available node tests are described in 4.6.4.2 Node Tests. Examples of steps are provided in 4.6.6 Unabbreviated Syntax and 4.6.7 Abbreviated Syntax.

4.6.4.1 Axes

Changes in 4.0  

  1. Four new axes have been defined: preceding-or-self, preceding-sibling-or-self, following-or-self, and following-sibling-or-self.   [Issue 1519 PR 1532 29 October 2024]

Axis::=("ancestor" | "ancestor-or-self" | "attribute" | "child" | "descendant" | "descendant-or-self" | "following" | "following-or-self" | "following-sibling" | "following-sibling-or-self" | "parent" | "preceding" | "preceding-or-self" | "preceding-sibling" | "preceding-sibling-or-self" | "self") "::"

An axis is essentially a function that takes a GNode (the origin) as input, and delivers a sequence of GNodes (always from within the same GTree as the origin) as its result.

XQuery supports the following axes:

  • The child axis contains the children of the origin.

    If the origin is an XNode, these are the XNodes returned by the [XDM 4.0] section 7.5.3 children Accessor accessor.

    Note:

    In an XTree, only document nodes and element nodes have children. If the origin is any other kind of XNode, or if the origin is an empty document or element node, then the child axis returns 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.

    If the origin is a JNode, these are the JNodes returned by the [TITLE OF DM40 SPEC, TITLE OF dm-jnode-children SECTION]j-childrenDM40DM accessor.

  • The descendant axis is defined as the transitive closure of the child axis; it contains the descendants of the origin (the children, the children of the children, and so on).

    More formally, $node/descendant::gnode() delivers the result of fn:transitive-closure($node, fn { child::gnode() }).

  • The descendant-or-self axis contains the origin and the descendants of the origin.

    More formally, $node/descendant-or-self::gnode() delivers the result of $node/(. | descendant::gnode()).

  • The parent axis returns the parent of the origin.

    If the origin is an XNode, this is the result of the [XDM 4.0] section 7.5.11 parent Accessor accessor.

    If the origin is a JNode, this is the value of the ·parent· property of the origin.

    If the GNode has no parent, the axis returns an empty sequence.

    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 origin (the parent, the parent of the parent, and so on).

    More formally, $node/ancestor::gnode() delivers the result of fn:transitive-closure($node, fn { parent::gnode() }).

    Note:

    The ancestor axis includes the root GNode of the GTree in which the origin is found, unless the origin is itself the root GNode.

  • The ancestor-or-self axis contains the origin and the ancestors of the origin; thus, the ancestor-or-self axis will always include the root.

    More formally, $node/ancestor-or-self::gnode() delivers the result of $node/(. | ancestor::gnode()).

  • The following-sibling axis returns the origin’s following siblings, that is, those children of the origin’s parent that occur after the origin in document order. If the origin is an attribute or namespace node, the following-sibling axis is empty.

    More formally, $node/following-sibling::gnode() delivers the result of fn:siblings($node)[. >> $node]).

  • The following-sibling-or-self axis contains the origin, together with the contents of the following-sibling axis.

    More formally, $node/following-sibling-or-self::gnode() delivers the result of fn:siblings($node)[not(. << $node)]

  • The preceding-sibling axis returns the origin’s preceding siblings, that is, those children of the origin’s parent that occur before the context node in document order. If the origin is an attribute or namespace node, the preceding-sibling axis is empty.

    More formally, $node/preceding-sibling::gnode() delivers the result of fn:siblings($node)[. << $node].

  • The preceding-sibling-or-self axis contains the origin, together with the contents of the preceding-sibling axis.

    More formally, $node/preceding-sibling-or-self::gnode() delivers the result of fn:siblings($node)[not(. >> $node).

  • The following axis contains all descendants of the root of the GTree in which the origin is found, are not descendants of the origin, and occur after the origin in document order.

    More formally, $node/following::gnode() delivers the result of $node/ancestor-or-self::gnode()/following-sibling::gnode()/descendant-or-self::gnode()

  • The following-or-self axis contains the origin, together with the contents of the following axis.

    More formally, $node/following-or-self::gnode() delivers the result of $node/(. | following::gnode()).

  • The preceding axis returns all descendants of the root of the GTree in which the origin is found, are not ancestors of the origin, and occur before the origin in document order.

    More formally, $node/preceding::gnode() delivers the result of $node/ancestor-or-self::gnode()/preceding-sibling::gnode()/descendant-or-self::gnode().

  • The preceding-or-self axis returns the origin, together with the contents of the preceding axis.

    More formally, $node/preceding-or-self::gnode() delivers the result of $node/(. | preceding::gnode()).

  • The attribute axis is defined only for XNodes. It returns the attributes of the origin, which are the nodes returned by the [XDM 4.0] section 7.5.1 attributes Accessor; the axis will be empty unless the context node is an element.

    If the attribute axis is applied to a JNode, a type error [err:XPTY0004] is raised.

  • The self axis contains just the origin itself.

    The self axis is primarily useful when testing whether the origin satisfies particular conditions, for example if ($x[self::chapter]).

    More formally, $node/self::gnode() delivers the result of $node.

Axes can be categorized as forward axes and reverse axes. An axis that only ever contains the origin 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, preceding-or-self, preceding-sibling, and preceding-sibling-or-self axes are reverse axes; all other axes are forward axes.

The ancestor, descendant, following, preceding and self axes partition a GTree (ignoring attribute nodes): they do not overlap and together they contain all the GNodes in the GTree.

[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 all other axes, the principal node kind is element.

4.6.5 Predicates within Steps

AxisStep::=(AbbreviatedStep | FullStep) Predicate*
AbbreviatedStep::=".." | ("@" NodeTest) | SimpleNodeTest
FullStep::=AxisNodeTest
Axis::=("ancestor" | "ancestor-or-self" | "attribute" | "child" | "descendant" | "descendant-or-self" | "following" | "following-or-self" | "following-sibling" | "following-sibling-or-self" | "parent" | "preceding" | "preceding-or-self" | "preceding-sibling" | "preceding-sibling-or-self" | "self") "::"
NodeTest::=UnionNodeTest | SimpleNodeTest
PredicatePredicatePredicatePredicate::="[" Expr "]"
ExprExprExprExpr::=(ExprSingle ++ ",")

A predicate within an AxisStep 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.

Note:

The operator [] binds more tightly than /. This means that the expression a/b[1] is interpreted as child::a/(child::b[1]): it selects the first b child of every a element, in contrast to (a/b)[1] which selects the first b element that is a child of some a element.

A common mistake is to write //a[1] where (//a)[1] is intended. The first expression, //a[1], selects every descendant a element that is the first child of its parent (it expands to /descendant-or-self::node()/child::a[1]), whereas (//a)[1] selects the a element in the document.

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.

More formally:

  • For a step using a forwards axis, such as child::test[P], the result is the same as for the equivalent filter expression(child::test)[P] (note the parentheses). The same applies if there are multiple predicates, for example child::test[P1][P2][P3] is equivalent to (child::test)[P1][P2][P3].

  • For a step using a reverse axis, such as ancestor::test[P], the result is the same as the expression reverse(ancestor::test)[P] => reverse(). The same applies if there are multiple predicates, for example ancestor::test[P1][P2][P3] is equivalent to reverse(ancestor::test)[P1][P2][P3] => reverse().

Note:

The result of the expression preceding-sibling::* is in document order, but preceding-sibling::*[1] selects the last preceding sibling element, that is, the one that immediately precedes the context node.

Similarly, the expression preceding-sibling::x[1, 2, 3] selects the last three preceding siblings, returning them in document order. For example, given the input:

<doc><a/><b/><c/><d/><e/><f/></doc>

The result of //e ! preceding-sibling::*[1, 2, 3] is <b/>, <c/>, <d/>. The expression //e ! preceding-sibling::*[3, 2, 1] delivers exactly the same result.

Here are some examples of axis steps that contain predicates to select XNodes:

  • 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]
  • This example selects the innermost div ancestor of the context node:

    ancestor::div[1]
  • This example selects the outermost div ancestor of the context node:

    ancestor::div[last()]
  • This example selects the names of all the ancestor elements of the context node that have an @id attribute, outermost element first:

    ancestor::*[@id]

Note:

The expression ancestor::div[1] parses as an AxisStep with a reverse axis, and the position 1 therefore refers to the first ancestor div in reverse document order, that is, the innermost div. By contrast, (ancestor::div)[1] parses as a FilterExpr, and therefore returns the first qualifying div element in the order of the ancestor::div expression, which is 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.

The expression ancestor::(div1|div2)[1] does not have the same meaning as (ancestor::div1|ancestor::div2)[1]. In the first expression, the predicate [1] is within a step that uses a reverse axis, so nodes are counted in reverse document order. In the second expression, the predicate applies to the result of a union expression, so nodes are counted in document order.

When the context value for evaluation of a step includes multiple GNodes, the step is evaluated separately for each of those GNodes, and the results are combined, eliminating duplicates and sorting into document order.

Note:

To avoid reordering and elimination of duplicates, replace the step S by .!S.

4.7 Sequence Expressions

XQuery 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).

4.7.3 Combining GNode Sequences

UnionExpr::=IntersectExceptExpr (("union" | "|") IntersectExceptExpr)*
IntersectExceptExpr::=InstanceofExpr (("intersect" | "except") InstanceofExpr)*
InstanceofExpr::=TreatExpr ("instance" "of" SequenceType)?

XQuery 4.0 provides the following operators for combining sequences of GNodes:

  • The union and | operators are equivalent. They take two node sequences as operands and return a sequence containing all the GNodes that occur in either of the operands.

  • The intersect operator takes two GNodes sequences as operands and returns a sequence containing all the GNodes that occur in both operands.

  • The except operator takes two node sequences as operands and returns a sequence containing all the GNodes that occur in the first operand but not in the second operand.

All these operators eliminate duplicate GNodes from their result sequences based on GNode identity. The resulting sequence is returned in document order.

If an operand of union, intersect, or except contains an item that is not a GNode, a type error is raised [err:XPTY0004].

If an IntersectExceptExpr contains more than two InstanceofExpr operands, they are evaluated 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.

The following example demonstrates the use of the except operator with JNodes:

let $m := jtree($map)
for $e in $m/child::* except $m/child::xx 
return ...

Note:

Because the jnodefn:jtree creates a new JTree root, calling it twice potentially creates two different trees, in which the JNodes have different identity. The expression $map/child::* except $map/child::xx might therefore have the wrong effect, because JNodes in two different trees are being compared. For more details see the specification of the jnodefn:jtree function.

In addition to the sequence operators described here, see [Functions and Operators 4.0] section 2 Processing sequences for functions defined on sequences.

4.14 Maps and Arrays

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 [Functions and Operators 4.0] section 14 Processing maps and [Functions and Operators 4.0] section 15 Processing arrays, 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.

4.14.3 Lookup Expressions

Changes in 4.0  

  1. The lookup operator ? can now be followed by an arbitrary literal, for cases where keys are items other than integers or NCNames. It can also be followed by a variable reference or a context value reference.   [Issue 1996 PR 2134 29 July 2025]

The operator "?", known as the lookup operator, returns values found in the operand map or array.

4.14.3.3 Comparing Lookup and Path Expressions

Lookup expressions are retained in this specification with only minor changes from the previous version 3.1. They remain a convenient solution for simple lookups of entries in maps and arrays.

For more complex queries into trees of maps and arrays, XQuery 4.0 introduces a generalization of path expressions (see 4.6 Path Expressions) which can now handle JTrees as well as XTrees.

For simple expressions, the capabilities of the two constructs overlap. For example, if $m is a map, then the expressions $m?code = 3 and $m/code = 3 have the same effect. Path expressions, however, have more power, and with it, more complexity. The expression $m/code = 3 (unless simplified by an optimizer) effectively expands the expression to (jtree($m)/child::get("code") => jnode-valuecontent()) = 3: that is, the supplied map is wrapped in a JNode, the child axis returns a sequence of JNodes, and the ·content· properties of these JNodes are compared with the supplied value 3.

Whereas simple lookups of specific entries in maps and arrays work well, experience has shown that the ?* wildcard lookup can be problematic. This is because of the flattening effect: for example, given the array let $A := [(1,2), (3,4), (), 5] the result of the expression $A?* is the sequence (1, 2, 3, 4, 5) which loses information that might be needed for further processing. By contrast, the path expression $A/* (or $A/child::*) returns a sequence of four JNodes, whose ·content· properties are respectively (1,2), (3,4), (), and 5.

The result of a lookup expression is a simple value (the value of an entry in a map or a member of an array, or the sequence concatenation of several such values). By contrast, the result of a path expression applied to maps or arrays is always a sequence of JNodes. These JNodes can be used for further navigation. If only the ·content· properties of the JNodes are needed, these will usually be extracted automatically by virtue of the coercion rules: for example if the value is used in an arithmetic expression or a value comparison, atomization of the JNode automatically extracts its ·content·. In other cases the value can be extracted explicitly by a call of the jnode-valuejnode-content function.

Lookup expressions on arrays result in a dynamic error if the subscript is out of bounds, whereas the equivalent path expression succeeds, returning an empty sequence. For example array{1 to 5}?10 raises [err:FOAY0001]FO40, whereas array{1 to 5}/get(10) returns a empty sequence.

A XQuery 4.0 Grammar

A.1 EBNF

Changes in 4.0  

  1. The EBNF operators ++ and ** have been introduced, for more concise representation of sequences using a character such as "," as a separator. The notation is borrowed from Invisible XML.  [Issue 1366 PR 1498]

The grammar of XQuery 4.0 uses the same simple Extended Backus-Naur Form (EBNF) notation as [XML 1.0] with the following differences.

  • The notation XYZ ** "," indicates a sequence of zero or more occurrences of XYZ, with a single comma between adjacent occurrences.

  • The notation XYZ ++ "," indicates a sequence of one or more occurrences of XYZ, with a single comma between adjacent occurrences.

  • All named symbols have a name that begins with an uppercase letter.

  • It adds a notation for referring to productions in external specifications.

  • Comments or extra-grammatical constraints on grammar productions are between '/*' and '*/' symbols.

    • A 'xgc:' prefix is an extra-grammatical constraint, the details of which are explained in A.1.2 Extra-grammatical Constraints

    • A 'ws:' prefix explains the whitespace rules for the production, the details of which are explained in A.3.4 Whitespace Rules

    • A 'gn:' prefix means a 'Grammar Note', and is meant as a clarification for parsing rules, and is explained in A.1.3 Grammar Notes. These notes are not normative.

The terminal symbols for this grammar include the quoted strings used in the production rules below, and the terminal symbols defined in section A.3.1 Terminal Symbols. The grammar is a little unusual in that parsing and tokenization are somewhat intertwined: for more details see A.3 Lexical structure.

The EBNF notation is described in more detail in A.1.1 Notation.

AbbreviatedStep::=".." | ("@" NodeTest) | SimpleNodeTest
AbsolutePathExpr::=("/" RelativePathExpr?) | ("//" RelativePathExpr)
AdditiveExpr::=MultiplicativeExpr (("+" | "-") MultiplicativeExpr)*
AllowingEmpty::="allowing" "empty"
AndExpr::=ComparisonExpr ("and" ComparisonExpr)*
Annotation::="%" EQName ("(" (Constant ++ ",") ")")?
AnyArrayType::="array" "(" "*" ")"
AnyFunctionType::=("function" | "fn") "(" "*" ")"
AnyItemTest::="item" "(" ")"
AnyMapType::="map" "(" "*" ")"
AnyNodeKindTest::="node" "(" ")"
AnyRecordType::="record" "(" "*" ")"
AposAttrValueContent::=AposAttrContentChar
| CommonContent
Argument::=ExprSingle | ArgumentPlaceholder
ArgumentList::="(" ((PositionalArguments ("," KeywordArguments)?) | KeywordArguments)? ")"
ArgumentPlaceholder::="?"
ArrayConstructor::=SquareArrayConstructor | CurlyArrayConstructor
ArrayType::=AnyArrayType | TypedArrayType
ArrowExpr::=UnaryExpr (SequenceArrowTarget | MappingArrowTarget)*
ArrowTarget::=FunctionCall | RestrictedDynamicCall
AttributeName::=EQName
AttributeTest::="attribute" "(" (NameTestUnion ("," TypeName)?)? ")"
Axis::=("ancestor" | "ancestor-or-self" | "attribute" | "child" | "descendant" | "descendant-or-self" | "following" | "following-or-self" | "following-sibling" | "following-sibling-or-self" | "parent" | "preceding" | "preceding-or-self" | "preceding-sibling" | "preceding-sibling-or-self" | "self") "::"
AxisStep::=(AbbreviatedStep | FullStep) Predicate*
BaseURIDecl::="declare" "base-uri" URILiteral
BoundarySpaceDecl::="declare" "boundary-space" ("preserve" | "strip")
BracedAction::=EnclosedExpr
BracedSwitchCases::="{" SwitchCases "}"
BracedTypeswitchCases::="{" TypeswitchCases "}"
CaseClause::="case" (VarName "as")? SequenceTypeUnion "return" ExprSingle
CastableExpr::=CastExpr ("castable" "as" CastTarget "?"?)?
CastExpr::=PipelineExpr ("cast" "as" CastTarget "?"?)?
CastTarget::=TypeName | ChoiceItemType | EnumerationType
CatchClause::="catch" NameTestUnionEnclosedExpr
CDataSection::="<![CDATA[" CDataSectionContents "]]>"
/* ws: explicit */
CDataSectionContents::=(Char* - (Char* ']]>' Char*))
/* ws: explicit */
ChoiceItemType::="(" (ItemType ++ "|") ")"
CommentTest::="comment" "(" ")"
CommonContent::=PredefinedEntityRef | CharRef | "{{" | "}}" | EnclosedExpr
ComparisonExpr::=OtherwiseExpr ((ValueComp | GeneralComp | NodeComp) OtherwiseExpr)?
CompAttrConstructor::="attribute" CompNodeNameEnclosedExpr
CompCommentConstructor::="comment" EnclosedExpr
CompDocConstructor::="document" EnclosedExpr
CompElemConstructor::="element" CompNodeNameEnclosedContentExpr
CompNamespaceConstructor::="namespace" CompNodeNCNameEnclosedExpr
CompNodeName::=QNameLiteral | UnreservedName | ("{" Expr "}")
CompNodeNCName::=MarkedNCName | UnreservedNCName | ("{" Expr "}")
CompPIConstructor::="processing-instruction" CompNodeNCNameEnclosedExpr
CompTextConstructor::="text" EnclosedExpr
ComputedConstructor::=CompDocConstructor
| CompElemConstructor
| CompAttrConstructor
| CompNamespaceConstructor
| CompTextConstructor
| CompCommentConstructor
| CompPIConstructor
Constant::=StringLiteral | ("-"? NumericLiteral) | QNameLiteral | ("true" "(" ")") | ("false" "(" ")")
ConstructionDecl::="declare" "construction" ("strip" | "preserve")
ContextValueDecl::="declare" "context" (("value" ("as" SequenceType)?) | ("item" ("as" ItemType)?)) ((":=" VarValue) | ("external" (":=" VarDefaultValue)?))
ContextValueRef::="."
CopyNamespacesDecl::="declare" "copy-namespaces" PreserveMode "," InheritMode
CountClause::="count" VarName
CurlyArrayConstructor::="array" EnclosedExpr
CurrentVar::=VarName
DecimalFormatDecl::="declare" (("decimal-format" EQName) | ("default" "decimal-format")) (DFPropertyName "=" StringLiteral)*
DefaultCollationDecl::="declare" "default" "collation" URILiteral
DefaultNamespaceDecl::="declare" "fixed"? "default" ("element" | "function") "namespace" URILiteral
DFPropertyName::="decimal-separator" | "grouping-separator" | "infinity" | "minus-sign" | "NaN" | "percent" | "per-mille" | "zero-digit" | "digit" | "pattern-separator" | "exponent-separator"
DirAttributeList::=(S (QNameS? "=" S? DirAttributeValue)?)*
/* ws: explicit */
DirAttributeValue::=('"' (EscapeQuot | QuotAttrValueContent)* '"')
| ("'" (EscapeApos | AposAttrValueContent)* "'")
/* ws: explicit */
DirCommentConstructor::="<!--" DirCommentContents "-->"
/* ws: explicit */
DirCommentContents::=((Char - '-') | ("-" (Char - '-')))*
/* ws: explicit */
DirectConstructor::=DirElemConstructor
| DirCommentConstructor
| DirPIConstructor
DirElemConstructor::="<" QNameDirAttributeList ("/>" | (">" DirElemContent* "</" QNameS? ">"))
/* ws: explicit */
DirElemContent::=DirectConstructor
| CDataSection
| CommonContent
| ElementContentChar
DirPIConstructor::="<?" PITarget (SDirPIContents)? "?>"
/* ws: explicit */
DirPIContents::=(Char* - (Char* '?>' Char*))
/* ws: explicit */
DocumentTest::="document-node" "(" (ElementTest | SchemaElementTest | NameTestUnion)? ")"
DynamicFunctionCall::=PostfixExprPositionalArgumentList
ElementName::=EQName
ElementTest::="element" "(" (NameTestUnion ("," TypeName "?"?)?)? ")"
EmptyOrderDecl::="declare" "default" "order" "empty" ("greatest" | "least")
EnclosedContentExpr::=EnclosedExpr
EnclosedExpr::="{" Expr? "}"
EnumerationType::="enum" "(" (StringLiteral ++ ",") ")"
EQName::=QName | URIQualifiedName
Expr::=(ExprSingle ++ ",")
ExprSingle::=FLWORExpr
| QuantifiedExpr
| SwitchExpr
| TypeswitchExpr
| IfExpr
| TryCatchExpr
| OrExpr
ExtendedFieldDeclaration::=FieldDeclaration (":=" ExprSingle)?
ExtensibleFlag::="," "*"
ExtensionExpr::=Pragma+ "{" Expr? "}"
FieldDeclaration::=FieldName "?"? ("as" SequenceType)?
FieldName::=NCName | StringLiteral
FilterExpr::=PostfixExprPredicate
FilterExprAM::=PostfixExpr "?[" Expr "]"
FinallyClause::="finally" EnclosedExpr
FLWORExpr::=InitialClauseIntermediateClause* ReturnClause
ForBinding::=ForItemBinding | ForMemberBinding | ForEntryBinding
ForClause::="for" (ForBinding ++ ",")
ForEntryBinding::=((ForEntryKeyBindingForEntryValueBinding?) | ForEntryValueBinding) PositionalVar? "in" ExprSingle
ForEntryKeyBinding::="key" VarNameAndType
ForEntryValueBinding::="value" VarNameAndType
ForItemBinding::=VarNameAndTypeAllowingEmpty? PositionalVar? "in" ExprSingle
ForMemberBinding::="member" VarNameAndTypePositionalVar? "in" ExprSingle
FullStep::=AxisNodeTest
FunctionBody::=EnclosedExpr
FunctionCall::=EQNameArgumentList
/* xgc: reserved-function-names */
/* gn: parens */
FunctionDecl::="declare" Annotation* "function" EQName "(" ParamListWithDefaults? ")" TypeDeclaration? (FunctionBody | "external")
/* xgc: reserved-function-names */
FunctionItemExpr::=NamedFunctionRef | InlineFunctionExpr
FunctionSignature::="(" ParamList ")" TypeDeclaration?
FunctionType::=Annotation* (AnyFunctionType
| TypedFunctionType)
GeneralComp::="=" | "!=" | "<" | "<=" | ">" | ">="
GNodeType::="gnode" "(" ")"
GroupByClause::="group" "by" (GroupingSpec ++ ",")
GroupingSpec::=VarName (TypeDeclaration? ":=" ExprSingle)? ("collation" URILiteral)?
IfExpr::="if" "(" Expr ")" (UnbracedActions | BracedAction)
Import::=SchemaImport | ModuleImport
InheritMode::="inherit" | "no-inherit"
InitialClause::=ForClause | LetClause | WindowClause
InlineFunctionExpr::=Annotation* ("function" | "fn") FunctionSignature? FunctionBody
InstanceofExpr::=TreatExpr ("instance" "of" SequenceType)?
IntermediateClause::=InitialClause | WhereClause | WhileClause | GroupByClause | OrderByClause | CountClause
IntersectExceptExpr::=InstanceofExpr (("intersect" | "except") InstanceofExpr)*
ItemType::=RegularItemType | FunctionType | TypeName | ChoiceItemType
ItemTypeDecl::="declare" Annotation* "type" EQName "as" ItemType
JNodeType::="jnode" "(" SequenceType? ")"
KeySpecifier::=NCName | Literal | ContextValueRef | VarRef | ParenthesizedExpr | LookupWildcard
KeywordArgument::=EQName ":=" Argument
KeywordArguments::=(KeywordArgument ++ ",")
LetArrayBinding::="$" "[" (VarNameAndType ++ ",") "]" TypeDeclaration? ":=" ExprSingle
LetBinding::=LetValueBinding | LetSequenceBinding | LetArrayBinding | LetMapBinding
LetClause::="let" (LetBinding ++ ",")
LetMapBinding::="$" "{" (VarNameAndType ++ ",") "}" TypeDeclaration? ":=" ExprSingle
LetSequenceBinding::="$" "(" (VarNameAndType ++ ",") ")" TypeDeclaration? ":=" ExprSingle
LetValueBinding::=VarNameAndType ":=" ExprSingle
LibraryModule::=ModuleDeclProlog
Literal::=NumericLiteral | StringLiteral | QNameLiteral
Lookup::="?" KeySpecifier
LookupExpr::=PostfixExprLookup
LookupWildcard::="*"
MainModule::=PrologQueryBody
MapConstructor::="map"? "{" (MapConstructorEntry ** ",") "}"
MapConstructorEntry::=ExprSingle (":" ExprSingle)?
MappingArrowTarget::="=!>" ArrowTarget
MapType::=AnyMapType | TypedMapType
MarkedNCName::="#" NCName
MethodCall::=PostfixExpr "=?>" NCNamePositionalArgumentList
Module::=VersionDecl? (LibraryModule | MainModule)
ModuleDecl::="module" "namespace" NCName "=" URILiteralSeparator
ModuleImport::="import" "module" ("namespace" NCName "=")? URILiteral ("at" (URILiteral ++ ","))?
MultiplicativeExpr::=UnionExpr (("*" | "×" | "div" | "÷" | "idiv" | "mod") UnionExpr)*
NamedFunctionRef::=EQName "#" IntegerLiteral
/* xgc: reserved-function-names */
NamedRecordTypeDecl::="declare" Annotation* "record" EQName "(" (ExtendedFieldDeclaration ** ",") ExtensibleFlag? ")"
NamespaceDecl::="declare" "namespace" NCName "=" URILiteral
NamespaceNodeTest::="namespace-node" "(" ")"
NameTest::=EQName | Wildcard
NameTestUnion::=(NameTest ++ "|")
NextVar::="next" VarName
NodeComp::="is" | "is-not" | NodePrecedes | NodeFollows | "precedes-or-is" | "follows-or-is"
NodeConstructor::=DirectConstructor
| ComputedConstructor
NodeFollows::=">>" | "follows"
NodeKindTest::=DocumentTest
| ElementTest
| AttributeTest
| SchemaElementTest
| SchemaAttributeTest
| PITest
| CommentTest
| TextTest
| NamespaceNodeTest
| AnyNodeKindTest
NodePrecedes::="<<" | "precedes"
NodeTest::=UnionNodeTest | SimpleNodeTest
NumericLiteral::=IntegerLiteral | HexIntegerLiteral | BinaryIntegerLiteral | DecimalLiteral | DoubleLiteral
OccurrenceIndicator::="?" | "*" | "+"
/* xgc: occurrence-indicators */
OptionDecl::="declare" "option" EQNameStringLiteral
OrderByClause::="stable"? "order" "by" (OrderSpec ++ ",")
OrderedExpr::="ordered" EnclosedExpr
OrderingModeDecl::="declare" "ordering" ("ordered" | "unordered")
OrderModifier::=("ascending" | "descending")? ("empty" ("greatest" | "least"))? ("collation" URILiteral)?
OrderSpec::=ExprSingleOrderModifier
OrExpr::=AndExpr ("or" AndExpr)*
OtherwiseExpr::=StringConcatExpr ("otherwise" StringConcatExpr)*
ParamList::=(VarNameAndType ** ",")
ParamListWithDefaults::=(ParamWithDefault ++ ",")
ParamWithDefault::=VarNameAndType (":=" ExprSingle)?
ParenthesizedExpr::="(" Expr? ")"
PathExpr::=AbsolutePathExpr
| RelativePathExpr
/* xgc: leading-lone-slash */
PipelineExpr::=ArrowExpr ("->" ArrowExpr)*
PITest::="processing-instruction" "(" (NCName | StringLiteral)? ")"
PositionalArgumentList::="(" PositionalArguments? ")"
PositionalArguments::=(Argument ++ ",")
PositionalVar::="at" VarName
PostfixExpr::=PrimaryExpr | FilterExpr | DynamicFunctionCall | LookupExpr | MethodCall | FilterExprAM
Pragma::="(#" SEQName (SPragmaContents)? "#)"
/* ws: explicit */
PragmaContents::=(Char* - (Char* '#)' Char*))
PredicatePredicate::="[" Expr "]"
PreserveMode::="preserve" | "no-preserve"
PreviousVar::="previous" VarName
PrimaryExpr::=Literal
| VarRef
| ParenthesizedExpr
| ContextValueRef
| FunctionCall
| OrderedExpr
| UnorderedExpr
| NodeConstructor
| FunctionItemExpr
| MapConstructor
| ArrayConstructor
| StringTemplate
| StringConstructor
| UnaryLookup
Prolog::=((DefaultNamespaceDecl | Setter | NamespaceDecl | Import) Separator)* ((ContextValueDecl | VarDecl | FunctionDecl | ItemTypeDecl | NamedRecordTypeDecl | OptionDecl) Separator)*
QNameLiteral::="#" EQName
QuantifiedExpr::=("some" | "every") (QuantifierBinding ++ ",") "satisfies" ExprSingle
QuantifierBinding::=VarNameAndType "in" ExprSingle
QueryBody::=Expr
QuotAttrValueContent::=QuotAttrContentChar
| CommonContent
RangeExpr::=AdditiveExpr ("to" AdditiveExpr)?
RecordType::=AnyRecordType | TypedRecordType
RegularItemType::=AnyItemTest | NodeKindTest | GNodeType | JNodeType | MapType | ArrayType | RecordType | EnumerationType
RelativePathExpr::=StepExpr (("/" | "//") StepExpr)*
RestrictedDynamicCall::=(VarRef | ParenthesizedExpr | FunctionItemExpr | MapConstructor | ArrayConstructor) PositionalArgumentList
ReturnClause::="return" ExprSingle
SchemaAttributeTest::="schema-attribute" "(" AttributeName ")"
SchemaElementTest::="schema-element" "(" ElementName ")"
SchemaImport::="import" "schema" SchemaPrefix? URILiteral ("at" (URILiteral ++ ","))?
SchemaPrefix::=("namespace" NCName "=") | ("fixed"? "default" "element" "namespace")
Selector::=EQName | Wildcard | ("get" "(" ExprSingle ")")
Separator::=";"
SequenceArrowTarget::="=>" ArrowTarget
SequenceType::=("empty-sequence" "(" ")")
| (ItemTypeOccurrenceIndicator?)
SequenceTypeUnion::=SequenceType ("|" SequenceType)*
Setter::=BoundarySpaceDecl | DefaultCollationDecl | BaseURIDecl | ConstructionDecl | OrderingModeDecl | EmptyOrderDecl | CopyNamespacesDecl | DecimalFormatDecl
SimpleMapExpr::=PathExpr ("!" PathExpr)*
SimpleNodeTest::=TypeTest | Selector
SlidingWindowClause::="sliding" "window" VarNameAndType "in" ExprSingleWindowStartCondition? WindowEndCondition
SquareArrayConstructor::="[" (ExprSingle ** ",") "]"
StepExpr::=PostfixExpr | AxisStep
StringConcatExpr::=RangeExpr ("||" RangeExpr)*
StringConstructor::="``[" StringConstructorContent "]``"
/* ws: explicit */
StringConstructorChars::=(Char* - (Char* ('`{' | ']``') Char*))
/* ws: explicit */
StringConstructorContent::=StringConstructorChars (StringInterpolationStringConstructorChars)*
/* ws: explicit */
StringInterpolation::="`{" Expr? "}`"
StringTemplate::="`" (StringTemplateFixedPart | StringTemplateVariablePart)* "`"
/* ws: explicit */
StringTemplateFixedPart::=((Char - ('{' | '}' | '`')) | "{{" | "}}" | "``")+
/* ws: explicit */
StringTemplateVariablePart::=EnclosedExpr
SwitchCaseClause::=("case" SwitchCaseOperand)+ "return" ExprSingle
SwitchCaseOperand::=Expr
SwitchCases::=SwitchCaseClause+ "default" "return" ExprSingle
SwitchComparand::="(" Expr? ")"
SwitchExpr::="switch" SwitchComparand (SwitchCases | BracedSwitchCases)
TextTest::="text" "(" ")"
TreatExpr::=CastableExpr ("treat" "as" SequenceType)?
TryCatchExpr::=TryClause ((CatchClause+ FinallyClause?) | FinallyClause)
TryClause::="try" EnclosedExpr
TumblingWindowClause::="tumbling" "window" VarNameAndType "in" ExprSingleWindowStartCondition? WindowEndCondition?
TypedArrayType::="array" "(" SequenceType ")"
TypeDeclaration::="as" SequenceType
TypedFunctionParam::=("$" EQName "as")? SequenceType
TypedFunctionType::=("function" | "fn") "(" (TypedFunctionParam ** ",") ")" "as" SequenceType
TypedMapType::="map" "(" ItemType "," SequenceType ")"
TypedRecordType::="record" "(" (FieldDeclaration ** ",") ExtensibleFlag? ")"
TypeName::=EQName
TypeswitchCases::=CaseClause+ "default" VarName? "return" ExprSingle
TypeswitchExpr::="typeswitch" "(" Expr ")" (TypeswitchCases | BracedTypeswitchCases)
TypeTest::=RegularItemType | ("type" "(" SequenceType ")")
UnaryExpr::=("-" | "+")* ValueExpr
UnaryLookup::=Lookup
UnbracedActions::="then" ExprSingle "else" ExprSingle
UnionExpr::=IntersectExceptExpr (("union" | "|") IntersectExceptExpr)*
UnionNodeTest::="(" (SimpleNodeTest ++ "|") ")"
UnorderedExpr::="unordered" EnclosedExpr
UnreservedName::=EQName
/* xgc: unreserved-name */
UnreservedNCName::=NCName
/* xgc: unreserved-name */
URILiteral::=StringLiteral
ValidateExpr::="validate" (ValidationMode | ("type" TypeName))? "{" Expr "}"
ValidationMode::="lax" | "strict"
ValueComp::="eq" | "ne" | "lt" | "le" | "gt" | "ge"
ValueExpr::=ValidateExpr | ExtensionExpr | SimpleMapExpr
VarDecl::="declare" Annotation* "variable" VarNameAndType ((":=" VarValue) | ("external" (":=" VarDefaultValue)?))
VarDefaultValue::=ExprSingle
VarName::="$" EQName
VarNameAndType::="$" EQNameTypeDeclaration?
VarRef::="$" EQName
VarValue::=ExprSingle
VersionDecl::="xquery" (("encoding" StringLiteral) | ("version" StringLiteral ("encoding" StringLiteral)?)) Separator
WhereClause::="where" ExprSingle
WhileClause::="while" ExprSingle
Wildcard::="*"
| (NCName ":*")
| ("*:" NCName)
| (BracedURILiteral "*")
/* ws: explicit */
WindowClause::="for" (TumblingWindowClause | SlidingWindowClause)
WindowEndCondition::="only"? "end" WindowVars ("when" ExprSingle)?
WindowStartCondition::="start" WindowVars ("when" ExprSingle)?
WindowVars::=CurrentVar? PositionalVar? PreviousVar? NextVar?