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.8 Arithmetic Expressions

Changes in 4.0  

  1. The symbols × and ÷ can be used for multiplication and division.

XQuery 4.0 provides binary arithmetic operators for addition, subtraction, multiplication, division, and modulus, in their usual binary and unary forms.:

AdditiveExpr::=MultiplicativeExpr (("+" | "-") MultiplicativeExpr)*
MultiplicativeExpr::=UnionExpr (("*" | "×" | "div" | "÷" | "idiv" | "mod") UnionExpr)*
UnionExpr::=IntersectExceptExpr (("union" | "|") IntersectExceptExpr)*

In addition, unary operators are provided for addition and subtraction:

AdditiveExpr::=MultiplicativeExpr (("+" | "-") MultiplicativeExpr)*
MultiplicativeExpr::=UnionExpr (("*" | "×" | "div" | "÷" | "idiv" | "mod") UnionExpr)*
UnionExpr::=IntersectExceptExpr (("union" | "|") IntersectExceptExpr)*
UnaryExpr::=("-" | "+")* ValueExpr
ValueExprValueExpr::=ValidateExpr | ExtensionExpr | SimpleMapExpr
ValidateExprValidateExpr::="validate" (ValidationMode | ("type" TypeName))? "{" Expr "}"
ExtensionExprExtensionExpr::=Pragma+ "{" Expr? "}"
SimpleMapExprSimpleMapExpr::=PathExpr ("!" PathExpr)*

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.3.5 Whitespace Rules for further details on whitespace handling.)

The arithmetic operator symbols * and ×U+00D7 (xD7MULTIPLICATION SIGN, ×) are interchangeable, and denote multiplication.

The arithmetic operator symbols div and ÷U+00F7 (xF7DIVISION SIGN, ÷) are interchangeable, and denote division.

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 operand (for a unary operator) or operands (for a binary operator). The order in which the operands are evaluated is implementation-dependent.

Each operand is evaluated by applying the following steps, in order:

  1. Atomization is applied to the operand. The result of this operation is called the atomized operand.

  2. 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.

  3. If the atomized operand is a sequence of length greater than one, a type error is raised [err:XPTY0004].

  4. 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]FO40

If, after this process, both operands of a binary arithmetic operator are instances of xs:numeric but have different primitive types, they are coerced to a common type by applying the following rules:

  1. If either of the items is of type xs:double, then both the values are cast to type xs:double.

  2. Otherwise, if either of the items is of type xs:float, then both the values are cast to type xs:float.

  3. Otherwise, no casting takes place: the values remain as xs:decimal.

After this preparation, the arithmetic expression is evaluated by applying the appropriate function listed in the table below. The definitions of these functions are found in [XQuery and XPath Functions and Operators 4.0].

Unary Arithmetic Operators
ExpressionType of AFunctionResult type
+ Axs:numericop:numeric-unary-plus(A)xs:numeric
- Axs:numericop:numeric-unary-minus(A)xs:numeric
Binary Arithmetic Operators
ExpressionType of AType of BFunctionResult type
A + Bxs:numericxs:numericop:numeric-add(A, B)xs:numeric
A + Bxs:datexs:yearMonthDurationop:add-yearMonthDuration-to-date(A, B)xs:date
A + Bxs:yearMonthDurationxs:dateop:add-yearMonthDuration-to-date(B, A)xs:date
A + Bxs:datexs:dayTimeDurationop:add-dayTimeDuration-to-date(A, B)xs:date
A + Bxs:dayTimeDurationxs:dateop:add-dayTimeDuration-to-date(B, A)xs:date
A + Bxs:timexs:dayTimeDurationop:add-dayTimeDuration-to-time(A, B)xs:time
A + Bxs:dayTimeDurationxs:timeop:add-dayTimeDuration-to-time(B, A)xs:time
A + Bxs:dateTimexs:yearMonthDurationop:add-yearMonthDuration-to-dateTime(A, B)xs:dateTime
A + Bxs:yearMonthDurationxs:dateTimeop:add-yearMonthDuration-to-dateTime(B, A)xs:dateTime
A + Bxs:dateTimexs:dayTimeDurationop:add-dayTimeDuration-to-dateTime(A, B)xs:dateTime
A + Bxs:dayTimeDurationxs:dateTimeop:add-dayTimeDuration-to-dateTime(B, A)xs:dateTime
A + Bxs:yearMonthDurationxs:yearMonthDurationop:add-yearMonthDurations(A, B)xs:yearMonthDuration
A + Bxs:dayTimeDurationxs:dayTimeDurationop:add-dayTimeDurations(A, B)xs:dayTimeDuration
A - Bxs:numericxs:numericop:numeric-subtract(A, B)xs:numeric
A - Bxs:datexs:dateop:subtract-dates(A, B)xs:dayTimeDuration
A - Bxs:datexs:yearMonthDurationop:subtract-yearMonthDuration-from-date(A, B)xs:date
A - Bxs:datexs:dayTimeDurationop:subtract-dayTimeDuration-from-date(A, B)xs:date
A - Bxs:timexs:timeop:subtract-times(A, B)xs:dayTimeDuration
A - Bxs:timexs:dayTimeDurationop:subtract-dayTimeDuration-from-time(A, B)xs:time
A - Bxs:dateTimexs:dateTimeop:subtract-dateTimes(A, B)xs:dayTimeDuration
A - Bxs:dateTimexs:yearMonthDurationop:subtract-yearMonthDuration-from-dateTime(A, B)xs:dateTime
A - Bxs:dateTimexs:dayTimeDurationop:subtract-dayTimeDuration-from-dateTime(A, B)xs:dateTime
A - Bxs:yearMonthDurationxs:yearMonthDurationop:subtract-yearMonthDurations(A, B)xs:yearMonthDuration
A - Bxs:dayTimeDurationxs:dayTimeDurationop:subtract-dayTimeDurations(A, B)xs:dayTimeDuration
A * Bxs:numericxs:numericop:numeric-multiply(A, B)xs:numeric
A * Bxs:yearMonthDurationxs:numericop:multiply-yearMonthDuration(A, B)xs:yearMonthDuration
A * Bxs:numericxs:yearMonthDurationop:multiply-yearMonthDuration(B, A)xs:yearMonthDuration
A * Bxs:dayTimeDurationxs:numericop:multiply-dayTimeDuration(A, B)xs:dayTimeDuration
A * Bxs:numericxs:dayTimeDurationop:multiply-dayTimeDuration(B, A)xs:dayTimeDuration
A idiv Bxs:numericxs:numericop:numeric-integer-divide(A, B)xs:integer
A div Bxs:numericxs:numericop:numeric-divide(A, B)numeric; but xs:decimal if both operands are xs:integer
A div Bxs:yearMonthDurationxs:numericop:divide-yearMonthDuration(A, B)xs:yearMonthDuration
A div Bxs:dayTimeDurationxs:numericop:divide-dayTimeDuration(A, B)xs:dayTimeDuration
A div Bxs:yearMonthDurationxs:yearMonthDurationop:divide-yearMonthDuration-by-yearMonthDuration(A, B)xs:decimal
A div Bxs:dayTimeDurationxs:dayTimeDurationop:divide-dayTimeDuration-by-dayTimeDuration(A, B)xs:decimal
A mod Bxs:numericxs:numericop:numeric-mod(A, B)xs:numeric

Note:

The operator symbol × is a synonym of *, while ÷ is a synonym of div.

If there is no entry in the table for the combination of operator and operands, then a type error is raised [err:XPTY0004].

Errors may also occur during coercion of the operands, or during evaluation of the identified function (for example, an error might result from dividing by zero).

Note:

XQuery 4.0 provides three division operators:

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 (though not useful).

Note:

Negation is not the same as subtraction from zero: if $x is positive zero, then -$x returns negative zero, wheras 0 - $x returns positive zero.