This article is part of the [[XQuery|XQuery Portal]]. It provides a summary of the most important features of the [httphttps://www.w3.org/TR/xquery-30/ XQuery 3.0] Recommendation.
=Enhanced FLWOR Expressions=
'''Example:'''
<syntaxhighlight pre lang="'xquery"'>for $country in db:openget('factbook')//country
where $country/@population > 100000000
for $city in $country//city[population > 1000000]
count $id
return <country id='{ $id }' name='{ $name }'>{ $city/name }</country>
</syntaxhighlightpre>
==group by==
FLWOR expressions have been extended to include the [httphttps://www.w3.org/TR/xquery-30/#id-group-by group by] clause, which is well-established in SQL. <code>group by</code> can be used to apply value-based partitioning to query results:
'''XQuery:'''
<syntaxhighlight pre lang="'xquery"'>
for $ppl in doc('xmark')//people/person
let $ic := $ppl/profile/@income
let $income := if($ic < 30000) then "challenge" else if($ic >= 30000 and $ic < 100000) then "standard" else if($ic >= 100000) then "preferred" else "na"
group by $income
order by $income
return element { $income } { count($ppl) }
</syntaxhighlightpre>
This query is a rewrite of [httphttps://www.ins.cwi.nl/projects/xmark/Assets/xmlquery.txt Query #20] contained in the [httphttps://www.insprojects.cwi.nl/projectsxmark/xmark XMark Benchmark Suite] to use <code>group by</code>.
The query partitions the customers based on their income.
'''Result:'''
<syntaxhighlight pre lang="xml">
<challenge>4731</challenge>
<na>12677</na>
<preferred>314</preferred>
<standard>7778</standard>
</syntaxhighlightpre>
In contrast to the relational GROUP BY statement, the XQuery counterpart concatenates the values of all non-grouping variables that belong to a specific group. In the context of our example, all nodes in <code>//people/person</code> that belong to the <code>preferred</code> partition are concatenated in <code class="brush:xquery">$ppl</code> after grouping has finished. You can see this effect by changing the return statement to:
<syntaxhighlight pre lang="'xquery"'>
...
return element { $income } { $ppl }
</syntaxhighlightpre>
'''Result:'''
<syntaxhighlight pre lang="xml">
<challenge>
<person id="person0">
…
</challenge>
</syntaxhighlightpre>
Moreover, a value can be assigned to the grouping variable. This is shown in the following example:
'''XQuery:'''
<syntaxhighlight pre lang="'xquery"'>
let $data :=
<xml>
</xml>
for $person in $data/person
group by $country := $person/@country/string()
return element persons {
attribute country { $country },
for $name in $person/@name ! return element name { data($name) }
}
</syntaxhighlightpre>
'''Result:'''
<syntaxhighlight pre lang="xml">
<persons country="USA">
<name>John</name>
<name>Johann</name>
</persons>
</syntaxhighlightpre>
==count==
The {{Code|count}} clause enhances the FLWOR expression with a variable that enumerates the iterated tuples.
<syntaxhighlight pre lang="'xquery"'>
for $n in (1 to 10)[. mod 2 = 1]
count $c
return <<number count="{ $c }" number="{ $n }"/>></syntaxhighlightpre>
==allowing empty==
The {{Code|allowing empty}} provides functionality similar to outer joins in SQL:
<syntaxhighlight pre lang="'xquery"'>
for $n allowing empty in ()
return 'empty? ' || empty($n)
</syntaxhighlightpre>
==window==
Window clauses provide a rich set of variable declarations to process sub-sequences of iterated tuples. An example:
<syntaxhighlight pre lang="'xquery"'>
for tumbling window $w in (2, 4, 6, 8, 10, 12, 14)
start at $s when fn:true()
only end at $e when $e - $s eq 2
return <<window>>{ $w }<</window>></syntaxhighlightpre>
More information on window clauses, and all other enhancements, can be found in the [httphttps://www.w3.org/TR/xquery-30/#id-windows specification].
=Function Items=
<ul>
<li>Declaring a new ''inline function'':
<syntaxhighlight pre lang="'xquery"'>let $f := function($x, $y) { $x + $y }return $f(17, 25)</syntaxhighlightpre>
'''Result:''' <code>42</code>
</li>
<li>Getting the function item of an existing (built-in or user-defined) XQuery function. The arity (number of arguments) has to be specified as there can be more than one function with the same name:
<syntaxhighlight pre lang="'xquery"'>let $f := math:pow#2return $f(5, 2)</syntaxhighlightpre>
'''Result:''' <code>25</code>
</li>
<li>''Partially applying'' another function or function item. This is done by supplying only some of the required arguments, writing the placeholder <code>?</code> in the positions of the arguments left out. The produced function item has one argument for every placeholder.
<syntaxhighlight pre lang="'xquery"'>let $f := fn:substring(?, 1, 3)
return (
$f('foo123'),
$f('bar456')
)</syntaxhighlightpre>
'''Result:''' <code>foo bar</code>
</li>
</ul>
Function items can also be passed as arguments to and returned as results from functions. These so-called [[Higher-Order Functions]] like <code>fn:mapfor-each</code> and <code>fn:fold-left</code> are discussed in more depth on their own Wiki page.
=Simple Map Operator=
The [httphttps://www.w3.org/TR/xquery-30/#id-map-operator simple map] operator {{Code|!}} provides a compact notation for applying the results of a first to a second expression: the resulting items of the first expression are bound to the context item one by one, and the second expression is evaluated for each item. The map operator may be used as replacement for FLWOR expressions:
'''Example:'''
<syntaxhighlight pre lang="'xquery"'>
(: Simple map notation :)
(1 to 10) ! element node { . },
for $i in 1 to 10
return element node { $i }
</syntaxhighlightpre>
In contrast to path expressions, the results of the map operator will not be made duplicate-free and returned in document order.
=Try/Catch=
The [httphttps://www.w3.org/TR/xquery-30/#id-try-catch try/catch] construct can be used to handle errors at runtime:
'''Example:'''
<syntaxhighlight pre lang="'xquery"'>
try {
1 + '2'
'Error [' || $err:code || ']: ' || $err:description
}
</syntaxhighlightpre>
'''Result:''' <code>Typing error: '+' operator: number expected, xs:string found.</code>
* {{Code|$err:line-number}}: line number where the error occurred
* {{Code|$err:column-number}}: column number where the error occurred
* {{Code|$err:additional}}: error stack trace
=Switch=
The [httphttps://www.w3.org/TR/xquery-30/#id-switch switch] statement is available in many other programming languages. It chooses one of several expressions to evaluate based on its input value.
'''Example:'''
<syntaxhighlight pre lang="'xquery"'>
for $fruit in ("Apple", "Pear", "Peach")
return switch ($fruit)
case "Peach" return "pink"
default return "unknown"
</syntaxhighlightpre>
'''Result:''' <code>red green pink</code>
'''Example:'''
<syntaxhighlight pre lang="'xquery"'>
for $fruit in ("Apple", "Cherry")
return switch ($fruit)
default
return "unknown"
</syntaxhighlightpre>
'''Result:''' <code>red red</code>
=Expanded QNames=
A ''QName'' can be prefixed with the letter "{{Code|Q" and a }}, the namespace URI wrapped in curly braces and the [http://www.jclark.com/xml/xmlns.htm Clark Notation]local name.
'''Examples:'''
New namespaces can be created via so-called 'Computed Namespace Constructors'.
<syntaxhighlight pre lang="'xquery"'>
element node { namespace pref { 'http://url.org/' } }
</syntaxhighlightpre>
=String Concatenations=
Two vertical bars <code>||</code> (also named ''pipe characters'') can be used to concatenate strings. This operator is a shortcut for the {{Code|fn:concat()}} function.
<syntaxhighlight pre lang="'xquery"'>
'Hello' || ' ' || 'Universe'
</syntaxhighlightpre>
=External Variables=
Default values can be attached to external variable declarations. This way, an expression can also be evaluated if its external variables have not been bound to a new value.
<syntaxhighlight pre lang="'xquery"'>
declare variable $user external := "admin";
"User:", $user
</syntaxhighlightpre>
=Serialization=
[[Serialization|Serialization ]]parameters can be defined within XQuery expressions. Parameters are placed in the query prolog and need to be specified as option declarations, using the <code>output</code> prefix.
'''Example:'''
<syntaxhighlight pre lang="'xquery"'>
declare namespace output = "http://www.w3.org/2010/xslt-xquery-serialization";
declare option output:omit-xml-declaration "no";
declare option output:method "xhtml";
<<html/>></syntaxhighlightpre>
'''Result:''' <code><?xml version="1.0" encoding="UTF-8"?><html></html></code>
'''Example:'''
<syntaxhighlight pre lang="'xquery"'>
declare context item := document {
<xml>
for $t in .//text()
return string-length($t)
</syntaxhighlightpre>
'''Result:''' <code>5 5</code>
'''Example:'''
<syntaxhighlight pre lang="'xquery"'>
declare %private function local:max($x1, $x2) {
if($x1 > $x2) then $x1 else $x2
local:max(2, 3)
</syntaxhighlightpre>
=Functions=
The following functions have been added in the [httphttps://www.w3.org/TR/xpath-functions-3031/ XQuery 3.0 Functions and Operators] Specification:
<code>fn:analyze-string</code>* , <code>fn:available-environment-variables</code>, <code>fn:element-with-id</code>, <code>fn:environment-variable</code>, <code>fn:filter</code>, <code>fn:fold-left</code>, <code>fn:fold-right</code>, <code>fn:for-each</code>, <code>fn:for-each-pair</code>, <code>fn:format-date</code>, <code>fn:format-dateTime</code>, <code>fn:format-integer</code>, <code>fn:format-number</code>, <code>fn:format-time</code>, <code>fn:function-arity</code>, <code>fn:function-lookup</code>, <code>fn:function-name</code>, <code>fn:generate-id</code>, <code>fn:has-children</code>, <code>fn:head</code>, <code>fn:innermost</code>, <code>fn:outermost</code>, <code>fn:parse-xml</code>, <code>fn:parse-xml-fragment</code>, <code>fn:path</code>, <code>fn:serialize</code>, <code>fn:tail</code>, <code>fn:unparsed-text</code>, <code>fn:unparsed-text-available</code>, <code>fn:unparsed-text-lines</code>, <code>fn:uri-collection</code>
New signatures have been added for the following functions:
<code>fn:document-uri</code>, <code>fn:string-join</code>, <code>fn:node-name</code>, <code>fn:round</code>, <code>fn:data</code>
=Changelog=
;Version 8.4
* Added: %non-deterministic
;Version 8.0
* Added: %basex:inline, %basex:lazy
;Version 7.7