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 <http://www.saxonica.com/>

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 section describes the status of this document at the time of its publication. Other documents may supersede this document.

This document is a working draft developed and maintained by a W3C Community Group, the XQuery and XSLT Extensions Community Group unofficially known as QT4CG (where "QT" denotes Query and Transformation). This draft is work in progress and should not be considered either stable or complete. Standard W3C copyright and patent conditions apply.

The community group welcomes comments on the specification. Comments are best submitted as issues on the group's GitHub repository.

The community group maintains two extensive test suites, one oriented to XQuery and XPath, the other to XSLT. These can be found at qt4tests and xslt40-test respectively. New tests, or suggestions for correcting existing tests, are welcome. The test suites include extensive metadata describing the conditions for applicability of each test case as well as the expected results. They do not include any test drivers for executing the tests: each implementation is expected to provide its own test driver.

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.12 Node Constructors

XQuery provides node constructors that can create XML nodes within a query.

NodeConstructor::=DirectConstructor
| ComputedConstructor
DirectConstructor::=DirElemConstructor
| DirCommentConstructor
| DirPIConstructor
DirElemConstructor::="<" QNameDirAttributeList ("/>" | (">" DirElemContent* "</" QNameS? ">"))
/* ws: explicit */
DirAttributeList::=(S (QNameS? "=" S? DirAttributeValue)?)*
/* ws: explicit */
DirAttributeValue::=('"' (EscapeQuot | QuotAttrValueContent)* '"')
| ("'" (EscapeApos | AposAttrValueContent)* "'")
/* ws: explicit */
QuotAttrValueContent::=QuotAttrContentChar
| CommonContent
AposAttrValueContent::=AposAttrContentChar
| CommonContent
DirElemContent::=DirectConstructor
| CDataSection
| CommonContent
| ElementContentChar
DirCommentConstructor::="<!--" DirCommentContents "-->"
/* ws: explicit */
DirPIConstructor::="<?" PITarget (SDirPIContents)? "?>"
/* ws: explicit */
CDataSection::="<![CDATA[" CDataSectionContents "]]>"
/* ws: explicit */
CDataSectionContents::=(Char* - (Char* ']]>' Char*))
/* ws: explicit */
Char::=[http://www.w3.org/TR/REC-xml#NT-Char]XML
/* xgc: xml-version */
CommonContent::=PredefinedEntityRef | CharRef | "{{" | "}}" | EnclosedExpr
EnclosedExpr::="{" Expr? "}"
ElementContentChar::=(Char - [{}<&])
DirCommentContents::=((Char - '-') | ("-" (Char - '-')))*
/* ws: explicit */
ComputedConstructor::=CompDocConstructor
| CompElemConstructor
| CompAttrConstructor
| CompNamespaceConstructor
| CompTextConstructor
| CompCommentConstructor
| CompPIConstructor

Constructors are provided for element, attribute, document, text, comment, and processing instruction nodes. Two kinds of constructors are provided: direct constructors, which use an XML-like notation that can incorporate enclosed expressions, and computed constructors, which use a notation based on enclosed expressions.

The rest of this section contains a conceptual description of the semantics of various kinds of constructor expressions. An XQuery implementation is free to use any implementation technique that produces the same result as the processing steps described here.

4.12.3 Computed Constructors

ComputedConstructor::=CompDocConstructor
| CompElemConstructor
| CompAttrConstructor
| CompNamespaceConstructor
| CompTextConstructor
| CompCommentConstructor
| CompPIConstructor
CompDocConstructor::="document" EnclosedExpr
CompElemConstructor::="element" CompNodeNameEnclosedContentExpr
CompAttrConstructor::="attribute" CompNodeNameEnclosedExpr
CompNamespaceConstructor::="namespace" CompNodeNCNameEnclosedExpr
CompTextConstructor::="text" EnclosedExpr
CompCommentConstructor::="comment" EnclosedExpr
CompPIConstructor::="processing-instruction" CompNodeNCNameEnclosedExpr

An alternative way to create nodes is by using a computed constructor. A computed constructor begins with a keyword that identifies the type of node to be created: element, attribute, document, text, processing-instruction, comment, or namespace.

For those kinds of nodes that have names (element, attribute, processing instruction, and namespace nodes), the keyword that specifies the node kind is followed by the name of the node to be created. This name may be specified either as an EQName or as an expression enclosed in braces. [Definition: When an expression is used to specify the name of a constructed node, that expression is called the name expression of the constructor.]

The following example illustrates the use of computed element and attribute constructors in a simple case where the names of the constructed nodes are constants. This example generates exactly the same result as the first example in 4.12.1 Direct Element Constructors:

element book {
  attribute isbn { "isbn-0060229357" },
  element title { "Harold and the Purple Crayon" },
  element author {
    element first { "Crockett" },
    element last { "Johnson" }
  }
}

Note:

XQuery 4.0 allows the node name to be written in quotation marks (for example, element "book" {}, and at the same time it disallows the use of a defined set of language keywords without quotes: for example element div {} was allowed in XQuery 3.1 but must now be written element #div {} or element { "div" } {}. The reason for this incompatible change is that allowing map constructors to omit the map keyword would otherwise create an ambiguity: consider for example the expression element otherwise {}.

Because the list of reserved keywords may be extended in future versions of this specification, the safest strategy is to always use the QNameLiteral syntax (for example element #div). To avoid any dependency on the default namespace context, the form element Q{}div might also be used.

To write code that is portable between XQuery 3.1 and XQuery 4.0, the best advice is to use either the form element { "div" } or the form element Q{}div.

4.12.3.1 Computed Element Constructors

Changes in 4.0  

  1. When the element name matches a language keyword such as div or value, it must now be written as a QName literal. This is a backwards incompatible change.   [Issues 1450 1983 PRs 1480 1989 3 October 2024]

CompElemConstructor::="element" CompNodeNameEnclosedContentExpr
CompNodeName::=QNameLiteral | UnreservedName | ("{" Expr "}")
QNameLiteral::="#" EQName
UnreservedName::=EQName
/* xgc: unreserved-name */
EQName::=QName | URIQualifiedName
Expr::=(ExprSingle ++ ",")
EnclosedContentExpr::=EnclosedExpr
EnclosedExpr::="{" Expr? "}"

[Definition: A computed element constructor creates an element node, allowing both the name and the content of the node to be computed.]

The element name is determined by the CompNodeName, which may be provided in a number of ways:

  1. As a QName literal, for example:

    element #table {}
    element #html:table {}
    element #Q{}table {}
    element #Q{http://http://www.w3.org/1999/xhtml}table {}
    element #Q{http://http://www.w3.org/1999/xhtml}html:table {}

    A QName literal written as an unprefixed lexical QName (the first form above) is resolved using the constructed element namespace rule. This differs from the normal rules for evaluating a QName literal as an atomic item of type xs:QName.

    Note that the last twothird and fourth examples (#Q{}table and #Q{http://http://www.w3.org/1999/xhtml}table) will result in the name of the constructed element having no prefix, which may in turn trigger the generation of a default namespace declaration.

  2. As a simple EQName, for example:

    element table {}
    element html:table {}
    element Q{}table {}
    element Q{http://http://www.w3.org/1999/xhtml}table {}
    element Q{http://http://www.w3.org/1999/xhtml}html:table {}

    In XQuery 4.0 the first form (using an unprefixed lexical QName) is allowed only if the element name is not a reserved keyword (such as div or value): see unreserved-name. In all other cases, the effect is exactly the same as when a leading # is added to turn the EQName into a QName literal.

    This syntax is retained for compatibility, but is deprecated.

  3. As an expression in curly brackets. This is processed as follows:

    1. Atomization is applied to the value of the name expression. If the result of atomization is not a single atomic item of type xs:QName, xs:string, or xs:untypedAtomic, a type error is raised [err:XPTY0004].

    2. If the atomized value of the name expression is of type xs:QName, that expanded QName is used as the node-name property of the constructed element, retaining the prefix part of the QName.

    3. If the atomized value of the name expression is of type xs:string or xs:untypedAtomic, that value is converted to an expanded QNameas follows:

      1. Leading and trailing whitespace is removed.

      2. If the value is a lexical QName, it is expanded using the constructed element namespace rule.

      3. If the value is a URIin the form of a -qualified nameURIQualifiedName (Q{uri}local or Q{uri}prefix:local), it is converted to an expanded QName with the supplied namespace URI and local name, and with no prefixthe specified prefix if present.

      Note:

      This was under-specified in XQuery 3.1.

    4. If conversion of the atomized name expression to an expanded QName is not successful, a dynamic error is raised [err:XQDY0074].

The resulting expanded QName is used as the node-name property of the constructed element, retaining the prefix part of the QName (or its absence).

An error is raised [err:XQDY0096] if the node-name of the constructed element node has any of the following properties:

  • Its namespace prefix is xmlns.

  • Its namespace URI is http://www.w3.org/2000/xmlns/.

  • Its namespace prefix is xml and its namespace URI is not http://www.w3.org/XML/1998/namespace.

  • Its namespace prefix is other than xml and its namespace URI is http://www.w3.org/XML/1998/namespace.

The above error may be raised as a static error if the element name is computed statically; in other cases it must be raised as a dynamic error.

The content expression of a computed element constructor (if present) is processed in exactly the same way as an enclosed expression in the content of a direct element constructor, as described in Step 1e of 4.12.1.3 Content. The result of processing the content expression is a sequence of nodes called the content sequence. If the content expression is absent, the content sequence is an empty sequence.

Processing of the computed element constructor proceeds as follows:

  1. If the content sequence contains a document node, the document node is replaced in the content sequence by its children.

  2. Adjacent text nodes in the content sequence are merged into a single text node by concatenating their contents, with no intervening blanks. After concatenation, any text node whose content is a zero-length string is deleted from the content sequence.

  3. If the content sequence contains an attribute node or a namespace node following a node that is not an attribute node or a namespace node, a type error is raised [err:XQTY0024].

  4. The properties of the newly constructed element node are determined as follows:

    1. node-name is the expanded QName resulting from processing the specified CompNodeName, as described above.

    2. parent is empty.

    3. attributes consist of all the attribute nodes in the content sequence, in implementation-dependent order. Note that the parent property of each of these attribute nodes has been set to the newly constructed element node. If two or more attributes have the same node-name, a dynamic error is raised [err:XQDY0025]. If an attribute named xml:space has a value other than preserve or default, a dynamic error may be raised [err:XQDY0092].

    4. children consist of all the element, text, comment, and processing instruction nodes in the content sequence. Note that the parent property of each of these nodes has been set to the newly constructed element node.

    5. base-uri is set to the following value:

      1. If the constructed node has an attribute named xml:base, then the value of this attribute, resolved (if it is relative) against the Executable Base URI, as described in 2.5.6 Resolving a Relative URI Reference.

      2. Otherwise, the Executable Base URI.

    6. The in-scope namespaces are computed as described in 4.12.4 In-scope Namespaces of a Constructed Element.

    7. The nilled property is false.

    8. The string-value property is equal to the concatenated contents of the text-node descendants in document order.

    9. The typed-value property is equal to the string-value property, as an instance of xs:untypedAtomic.

    10. If construction mode in the static context is strip, the type-name property is xs:untyped. On the other hand, if construction mode is preserve, the type-name property is xs:anyType.

    11. The is-id and is-idrefs properties are set to false.

A computed element constructor might be used to make a modified copy of an existing element. For example, if the variable $e is bound to an element with numeric content, the following constructor might be used to create a new element with the same name and attributes as $e and with numeric content equal to twice the value of $e:

element { node-name($e) } { $e/@*, 2 * data($e) }

In this example, if $e is bound by the expression let $e := <length units="inches">{ 5 }</length>, then the result of the example expression is the element <length units="inches">10</length>.

Note:

The static type of the expression fn:node-name($e) is xs:QName?, denoting zero or one QName. The example can be successfully evaluated as written provided that $e is bound to exactly one element node with numeric content.

One important purpose of computed constructors is to allow the name of a node to be computed. We will illustrate this feature by an expression that translates the name of an element from one language to another. Suppose that the variable $dict is bound to a dictionary element containing a sequence of entry elements, each of which encodes translations for a specific word. Here is an example entry that encodes the German and Italian variants of the word “address”:

<entry word="address">
  <variant xml:lang="de">Adresse</variant>
  <variant xml:lang="it">indirizzo</variant>
</entry>

Suppose further that the variable $e is bound to the following element:

<address>123 Roosevelt Ave. Flushing, NY 11368</address>

Then the following expression generates a new element in which the name of $e has been translated into Italian and the content of $e (including its attributes, if any) has been preserved. The first enclosed expression after the element keyword generates the name of the element, and the second enclosed expression generates the content and attributes:

element {
  $dict/entry[@word = name($e)]/variant[@xml:lang = "it"]
} {
  $e/@*, $e/node()
}

The result of this expression is as follows:

<indirizzo>123 Roosevelt Ave. Flushing, NY 11368</indirizzo>
4.12.3.2 Computed Attribute Constructors

Changes in 4.0  

  1. When the attribute name matches a language keyword such as by or of, it must now be written as a QName literal. This is a backwards incompatible change.   [Issues 1450 1983 PRs 1480 1989 3 October 2024]

CompAttrConstructor::="attribute" CompNodeNameEnclosedExpr
CompNodeName::=QNameLiteral | UnreservedName | ("{" Expr "}")
QNameLiteral::="#" EQName
UnreservedName::=EQName
/* xgc: unreserved-name */
EQName::=QName | URIQualifiedName
Expr::=(ExprSingle ++ ",")
EnclosedExpr::="{" Expr? "}"

A computed attribute constructor creates a new attribute node, with its own node identity.

Attributes have no default namespace. The rules that expand attribute names create an implementation-dependent prefix if an attribute name has a namespace URI but no prefix is provided.

The attribute name may be provided in a number of ways:

  1. As a QName literal, for example:

    attribute #width {}
    attribute #xsi:type {}
    attribute #Q{}width {}
    attribute #Q{http://www.w3.org/2001/XMLSchema-instance}xsi:type {}
    attribute #Q{http://www.w3.org/2001/XMLSchema-instance}type {}

    A QName literal written as an unprefixed lexical QName (the first form above) is resolved using the no-namespace ruleno-namespace rule.

    Note that the last example (#Q{http://www.w3.org/2001/XMLSchema-instance}type) will result in the name of the constructed attribute having a system-generated prefix.

  2. As a simple EQName, for example:

    attribute width {}
    attribute xsi:type {}
    attribute Q{}width {}
    attribute Q{http://www.w3.org/2001/XMLSchema-instance}xsi:type {}
    attribute Q{http://www.w3.org/2001/XMLSchema-instance}type {}

    In XQuery 4.0 the first form (using an unprefixed lexical QName) is allowed only if the attribute name is not a reserved keyword (such as div or value): see unreserved-name. In all other cases, the effect is exactly the same as when a leading # is added to turn the EQName into a QName literal.

    This syntax is retained for compatibility, but is deprecated.

  3. As an expression in curly brackets. This is processed as follows:

    1. Atomization is applied to the result of the name expression. If the result of atomization is not a single atomic item of type xs:QName, xs:string, or xs:untypedAtomic, a type error is raised [err:XPTY0004].

    2. If the atomized value of the name expression is of type xs:QName:

      1. If the expanded QName returned by the atomized name expression has a namespace URI but has no prefix, it is given an implementation-dependent prefix.

      2. The resulting expanded QName (including its prefix) is used as the node-name property of the constructed attribute node.

    3. If the atomized value of the name expression is of type xs:string or xs:untypedAtomic, that value is converted to an expanded QNameas follows:

      1. Leading and trailing whitespace is removed.

      2. If the value is a lexical QName, it is expanded using the no-namespace rule.

      3. If the value is a URIin the form of a -qualified nameURIQualifiedName (Q{uri}local or Q{uri}prefix:local), it is converted to an expanded QName with the supplied namespace URI and, local name, and prefix, or with an implementation dependent prefix if none is supplied.

      4. If conversion of the atomized name expression to an expanded QName is not successful, a dynamic error is raised [err:XQDY0074].

      Note:

      This was under-specified in XQuery 3.1.

The resulting expanded QName (including its prefix) is used as the node-name property of the constructed attribute node. If expansion of the QName is not successful, a static error is raised [err:XPST0081].

If the keyword attribute is followed by a name expression, the name expression is processed as follows:

A dynamic error is raised [err:XQDY0044] if the node-name of the constructed attribute node has any of the following properties:

  • Its namespace prefix is xmlns.

  • It has no namespace prefix and its local name is xmlns.

  • Its namespace URI is http://www.w3.org/2000/xmlns/.

  • Its namespace prefix is xml and its namespace URI is not http://www.w3.org/XML/1998/namespace.

  • Its namespace prefix is other than xml and its namespace URI is http://www.w3.org/XML/1998/namespace.

The content expression of a computed attribute constructor is processed as follows:

  1. Atomization is applied to the result of the content expression, converting it to a sequence of atomic items. (If the content expression is absent, the result of this step is an empty sequence.)

  2. If the result of atomization is an empty sequence, the value of the attribute is the zero-length string. Otherwise, each atomic item in the atomized sequence is cast into a string.

  3. The individual strings resulting from the previous step are merged into a single string by concatenating them with a single space character between each pair. The resulting string becomes the string-value property of the new attribute node. The type annotation (type-name property) of the new attribute node is xs:untypedAtomic. The typed-value property of the attribute node is the same as its string-value, as an instance of xs:untypedAtomic.

  4. The parent property of the attribute node is set to empty.

  5. If the attribute name is xml:id, then xml:id processing is performed as defined in [XML ID]. This ensures that the attribute node has the type xs:ID and that its value is properly normalized. If an error is encountered during xml:id processing, an implementation may raise a dynamic error [err:XQDY0091].

  6. If the attribute name is xml:id, the is-id property of the resulting attribute node is set to true; otherwise the is-id property is set to false. The is-idrefs property of the attribute node is unconditionally set to false.

  7. If the attribute name is xml:space and the attribute value is other than preserve or default, a dynamic error may be raised [err:XQDY0092].

  • Example:

    attribute size { 4 + 3 }

    The string value of the size attribute is "7" and its type is xs:untypedAtomic.

  • Example:

    attribute {
      if ($sex = "M") then "husband" else "wife"
    } {
      <a>Hello</a>, 1 to 3, <b>Goodbye</b>
    }

    The name of the constructed attribute is either husband or wife. Its string value is "Hello 1 2 3 Goodbye".