Please check the errata for any errors or issues reported since publication.
See also translations.
This document is also available in these non-normative formats: XML.
Copyright © 2000 W3C® (MIT, ERCIM, Keio, Beihang). W3C liability, trademark and document use rules apply.
XML is a versatile markup language, capable of labeling the information content of diverse data sources, including structured and semi-structured documents, relational databases, and object repositories. A query language that uses the structure of XML intelligently can express queries across all these kinds of data, whether physically stored in XML or viewed as XML via middleware. This specification describes a query language called XQuery, which is designed to be broadly applicable across many types of XML data sources.
A list of changes made since XQuery 3.1 can be found in J Change Log.
This is a draft prepared by the QT4CG (officially registered in W3C as the XSLT Extensions Community Group). Comments are invited.
The publications of this community group are dedicated to our co-chair, Michael Sperberg-McQueen (1954–2024).
A query can be assembled from one or more fragments called modules. [Definition: A module is a fragment of XQuery code that conforms to the Module grammar and can independently undergo the static analysis phase described in 2.3.3 Expression Processing. Each module is either a main module or a library module.]
[Definition: A main module consists of a Prolog followed by a Query Body.] A query has exactly one main module. In a main module, the Query Body is evaluated with respect to the static and dynamic contexts of the main module in which it is found, and its value is the result of the query.
[Definition: A module that does not contain a Query Body is called a library module. A library module consists of a module declaration followed by a Prolog.] A library module cannot be evaluated directly; instead, it provides function and variable declarations that can be imported into other modules.
The XQuery syntax does not allow a module to contain both a module declaration and a Query Body.
[Definition: A Prolog is a series of declarations and imports that define the processing environment for the module that contains the Prolog.] Each declaration or import is followed by a semicolon. A Prolog is organized into two parts.
The first part of the Prolog consists of setters, imports, namespace declarations, and default namespace declarations. [Definition: Setters are declarations that set the value of some property that affects query processing, such as construction mode or default collation.] Namespace declarations and default namespace declarations affect the interpretation of lexical QNames within the query. Imports are used to import definitions from schemas and modules. [Definition: The target namespace of a module is the namespace of the objects (such as elements or functions) that it defines. ]
The second part of the Prolog consists of declarations of variables, functions, and options. These declarations appear at the end of the Prolog because they may be affected by declarations and imports in the first part of the Prolog.
[Definition: The Query Body, if present, consists of an expression that defines the result of the query.] Evaluation of expressions is described in 4 Expressions. A module can be evaluated only if it has a Query Body.
Although item type declarations, as described in 5.19 Item Type Declarations, can be used to give names to record types as well as any other item type, named record types as described in this section provide a more concise syntax, plus additional functionality. In particular:
Named record types can be recursive.
Named record types implicitly create a constructor function that can be used to create instances of the record type.
A field in a named record type can be a function that has implicit access to the record on which it is defined, rather like methods in object-oriented languages.
The syntax is as follows:
NamedRecordTypeDecl | ::= | "declare" Annotation* "record" EQName "(" (ExtendedFieldDeclaration ** ",") ExtensibleFlag? ")" |
Annotation | ::= | "%" EQName ("(" (AnnotationValue ++ ",") ")")? |
EQName | ::= | QName | URIQualifiedName |
ExtendedFieldDeclaration | ::= | FieldDeclaration (":=" ExprSingle)? |
FieldDeclaration | ::= | FieldName "?"? ("as" SequenceType)? |
FieldName | ::= | NCName | StringLiteral |
StringLiteral | ::= | AposStringLiteral | QuotStringLiteral |
| /* ws: explicit */ | ||
SequenceType | ::= | ("empty-sequence" "(" ")") |
ExprSingle | ::= | FLWORExpr |
ExtensibleFlag | ::= | "," "*" |
A named record declaration serves as both a named item type and as a function definition, and it therefore inherits rules from both these roles. In particular:
Its name must not be the same as the name of any other named item type, or any generalized atomic type, that is present in the same static context [err:XQST0048].
If the declaration is public and is within a library module, then its name must be in the target namespace of the library module [err:XQST0048].
As a function, it must not have an arity range that overlaps the arity range of any other function declaration having the same name in the same static context.
The order of field declarations is significant, because it determines the order of arguments in a call to the constructor function.
The fields must have distinct names. [err:XPST0021]
In order to work as both a record type and a function declaration, the names of the fields must be simple NCNames in no namespace; the names must not be written as string literals [err:XPST0003].
Note:
This is described here as a semantic constraint, but an implementation might choose to impose it at the level of the grammar.
If an initializing expression is present in an ExtendedFieldDeclaration, it must follow the rules for the initializing expression of a parameter in a function declaration, given in 5.18.3 Function Parameters. In particular, if any field has an initializing expression then all following fields must have an initializing expression.
Any annotations that are present, such as %public or %private, apply both to the item type declaration and to the function declaration.
This example demonstrates an XQuery library module that provides a new data type to manipulate sets of atomic items.
A query that incorporates this module (by referencing it in an import module declaration) can use constructs such as:
declare variable $empty-set as set:atomic-set
:= set:build(());declare variable $evens as set:atomic-set
:= set:build((1 to 100)[. mod 2 = 0]);declare variable $odds as set:atomic-set
:= set:build((1 to 100)) ? except($evens)declare function my:is-even ($n as xs:integer) as xs:boolean {
$evens ? contains($n)
};Here is the implementation of the package. It relies heavily on the use of the function annotation %method, which gives a function item contained in a map access to the containing map: methods are described in 4.5.6.1 Methods.
module namespace set = "http://qt4cg.org/atomic-set";
(:
This package defines a type set:atomic-set which represents
a set of distinct atomic items. Atomic items are considered
distinct based on the comparison function fn:atomic-equal.
An instance of an atomic set can be constructed using a function
call such as set:build((1, 3, 5, 7, 9)).
If $A and $B are instances of set:atomic-set, then they
can be manipulated using methods including:
$A?size() - returns the number of items in the set
$A?empty() - returns true if the set is empty
$A?contains($k) - determines whether $k is a member of the set
$A?contains-all($B) - returns true if $B is a subset of $A
$A?values() - returns the items in $A, as a sequence
$A?add($k) - returns a new atomic set containing an additional item
$A?remove($k) - returns a new atomic set in which the given item is absent
$A?union($B) - returns a new atomic set holding the union of $A and $B
$A?intersect($B) - returns a new atomic set holding the intersection of $A and $B
$A?except($B) - returns a new atomic set holding the difference of $A and $B
:)
declare %public record set:atomic-set (
_data as map(xs:anyAtomicType, xs:boolean),
size as %method fn() as xs:integer,
empty as %method fn() as xs:boolean,
contains as %method fn($value as xs:anyAtomicType) as xs:boolean,
contains-all as %method fn($value as set:atomic-set) as xs:boolean,
add as %method fn($item as xs:anyAtomicType) as set:atomic-set,
remove as %method fn($item as xs:anyAtomicType) as set:atomic-set,
union as fn($value as set:atomic-set) as set:atomic-set,
intersect as fn($value as set:atomic-set) as set:atomic-set,
except as fn($value as set:atomic-set) as set:atomic-set,
* );
declare %private variable DATA := "'_data'";
(:
The private function set:replaceData processes the internal map
by applying a supplied function, and returns a new atomic set
with the resulting internal map
:)
declare %private function set:replaceData (
$input as set:atomic-set,
$update as fn(map(*)) as map(*)) as map(xs:anyAtomicType, xs:boolean) {
map:put($input, $DATA, $update($input?$DATA))
}
declare %public function set:build (
$values as xs:anyAtomicType* := ()) {
{
_data:
map:build($values, values:=true#0, {'duplicates': 'use-first'}),
size:
%method fn() as xs:integer
{ map:size(?$DATA) },
empty:
%method fn() as xs:boolean
{ map:empty(?$DATA) },
contains:
%method fn($value as xs:anyAtomicType) as xs:boolean
{ map:contains(?$DATA, $value) },
contains-all:
%method fn($other as set:atomic-set) as xs:boolean
{ every($value, map:contains(?$DATA, ?)) },
values:
"%method fn() as xs:anyAtomicType*
{ keys(?$DATA) }"
add:
%method fn($value as xs:anyAtomicType) as xs:anyAtomicType*
{ set:replaceData(., map:put(?, $value, true())) },
remove:
%method fn($value as xs:anyAtomicType) as xs:anyAtomicType*
{ set:replaceData(., map:remove(?, $value)) },
union:
%method fn($other as set:atomic-set) as set:atomic-set
{ set:replaceData(., fn($this) {map:merge(($this, $other?$DATA),
{'duplicates': 'use-first'})})
},
intersect:
%method fn($other as set:atomic-set) as set:atomic-set
{ set:replaceData(., map:filter(?, $other?contains)) },
except=
%method fn($other as set:atomic-set) as set:atomic-set
{ set:replaceData(., map:remove(?, $other?values())) }
}
};| Editorial note | |
| The example is not yet tested. It could also be written using the new xsl:record instruction, which might be more concise. | |