Difference between revisions of "XQuery 3.0"

From BaseX Documentation
Jump to navigation Jump to search
m (Fix grammar)
Line 3: Line 3:
 
and [http://www.w3.org/TR/xpath-30/ XPath 3.0] Recommendations
 
and [http://www.w3.org/TR/xpath-30/ XPath 3.0] Recommendations
 
that have already been implemented in BaseX.
 
that have already been implemented in BaseX.
 +
 +
==General FLWOR Expressions==
 +
 +
{{Mark|Introduced with Version 7.7:}}
 +
 +
Most clauses of FLWOR expressions can now be specified in an arbitrary order: additional {{Code|let}} and {{Code|for}} clauses can be put after a {{Code|where}} clause, and multiple {{Code|where}}, {{Code|order by}} and {{Code|group by}} statements can be used. This means that many nested loops can now be reformulated as a single FLWOR expression.
 +
 +
'''Example:'''
 +
<pre class="brush:xquery">
 +
for $country in db:open('factbook')//country
 +
where $country/@population > 100000000
 +
let $name := $country/name[1]
 +
for $city in $country//city[population > 1000000]
 +
group by $name
 +
return <country name='{ $name }'>{ $city/name }</country>
 +
</pre>
  
 
==Simple Map Operator==
 
==Simple Map Operator==

Revision as of 18:34, 8 March 2013

This article is part of the XQuery Portal. It summarizes features of the upcoming XQuery 3.0 and XPath 3.0 Recommendations that have already been implemented in BaseX.

General FLWOR Expressions

Introduced with Version 7.7:

Most clauses of FLWOR expressions can now be specified in an arbitrary order: additional let and for clauses can be put after a where clause, and multiple where, order by and group by statements can be used. This means that many nested loops can now be reformulated as a single FLWOR expression.

Example:

for $country in db:open('factbook')//country
where $country/@population > 100000000
let $name := $country/name[1]
for $city in $country//city[population > 1000000]
group by $name
return <country name='{ $name }'>{ $city/name }</country>

Simple Map Operator

The simple map operator ! 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:

(: Simple map notation :)
(1 to 10) ! element node { . },
(: FLWOR notation :)
for $i in 1 to 10
return element node { $i }

A map operator is defined to be part of a path expression, which may now be mixed of path and map operators. In contrast to the map operator, the results of the map operator will not be made duplicate-free and returned in document order.

Group By

FLWOR expressions have been extended to include the group by clause, which is well-established among relational database systems. group by can be used to apply value-based partitioning to query results:

Example:

 
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) }

This query is a rewrite of Query #20 contained in the XMark Benchmark Suite to use group by. The query partitions the customers based on their income.

Result:

<challenge>4731</challenge>
<na>12677</na>
<prefered>314</prefered>
<standard>7778</standard>

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 //people/person that belong to the preferred partition are concatenated in $ppl after grouping has finished. You can see this effect by changing the return statement to:

 
...
return element { $income } { $ppl }

Result:

<challenge>
  <person id="person0">
    <name>Kasidit Treweek</name>
    …
  <person id="personX">
    …
</challenge>

Try/Catch

The try/catch construct can be used to handle errors at runtime:

Example:

try {
  1 + '2'
} catch err:XPTY0004 {
  'Typing error: ' || $err:description
} catch * {
  'Error [' || $err:code || ']: ' || $err:description
}

Result: Typing error: '+' operator: number expected, xs:string found.

Switch

The switch statement is available in many other programming languages. It chooses one of several expressions to evaluate based on its input value.

Example:

for $fruit in ("Apple", "Pear", "Peach")
return switch ($fruit)
  case "Apple" return "red"
  case "Pear"  return "green"
  case "Peach" return "pink"
  default      return "unknown"

Result: red green pink

Function Items

One of the most distinguishing features added in XQuery 3.0 are function items, also known as lambdas or lambda functions. They make it possible to abstract over functions and thus write more modular code.

Examples:

Function items can be obtained in three different ways:

  • Declaring a new inline function:
    let $f := function($x, $y) { $x + $y }
    return $f(17, 25)

    Result: 42

  • Getting the function item of an existing (built-in oder 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:
    let $f := math:pow#2
    return $f(5, 2)

    Result: 25

  • Partially applying another function or function item. This is done by supplying only some of the required arguments, writing the placeholder ? in the positions of the arguments left out. The produced function item has one argument for every placeholder.
    let $f := fn:substring(?, 1, 3)
    return (
      $f('foo123'),
      $f('bar456')
    )

    Result: foo bar

Function items can also be passed as arguments to and returned as results from functions. These so-called Higher-Order Functions like fn:map and fn:fold-left are discussed in more depth on their own Wiki page.

Expanded QNames

A QName can now be directly prefixed with the letter "Q" and a namespace URI in the Clark Notation.

Examples:

  • Q{http://www.w3.org/2005/xpath-functions/math}pi() returns the number π
  • Q{java:java.io.FileOutputStream}new("output.txt") creates a new Java file output stream

The syntax differed in older versions of the XQuery 3.0 specification, in which the prefixed namespace URI was quoted:

  • "http://www.w3.org/2005/xpath-functions/math":pi()
  • "java:java.io.FileOutputStream":new("output")

Namespace Constructors

New namespaces can now be created via so-called 'Computed Namespace Constructors'.

 
element node { namespace pref { 'http://url.org/' } }

String Concatenations

Two vertical bars || (also names pipe characters) can be used to concatenate strings. This operator is a shortcut for the fn:concat() function.

 
'Hello' || ' ' || 'Universe'

External Variables

Default values can now 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.

 
declare variable $user external := "admin";
"User:", $user

Serialization

Serialization parameters can now be defined within XQuery expressions. Parameters are placed in the query prolog and need to be specified as option declarations, using the output prefix.

Example:

declare namespace output = "http://www.w3.org/2010/xslt-xquery-serialization";
declare option output:omit-xml-declaration "no";
declare option output:method "xhtml";
<html/>

Result: <?xml version="1.0" encoding="UTF-8"?><html></html>

In BaseX, the output prefix is statically bound and can thus be omitted. Note that all namespaces need to be specified when using external APIs, such as XQJ.

Context Item

The context item can now be specified in the prolog of an XQuery expressions:

Example:

declare context item := document {
  <xml>
    <text>Hello</text>
    <text>World</text>
  </xml>
};

for $t in .//text()
return string-length($t)

Result: 5 5

Annotations

XQuery 3.0 introduces annotations to declare properties associated with functions and variables. For instance, a function may be declared %public, %private, or %updating.

Example:

declare %private function local:max($x1, $x2) {
  if($x1 > $x2) then $x1 else $x2
};

local:max(2, 3)

Functions

BaseX supports all functions that have been added in Version 3.0 of the XQuery Functions and Operators Working Draft. The new functions are listed below:

  • math:pi(), math:sin(), and many others (see Math Module)
  • fn:analyze-string()
  • fn:available-environment-variables()
  • fn:element-with-id()
  • fn:environment-variable()
  • fn:filter()
  • fn:fold-left()
  • fn:fold-right()
  • fn:format-date()
  • fn:format-dateTime()
  • fn:format-integer()
  • fn:format-number()
  • fn:format-time()
  • fn:function-arity()
  • fn:function-lookup()
  • fn:function-name()
  • fn:generate-id()
  • fn:has-children()
  • fn:head()
  • fn:innermost()
  • fn:map()
  • fn:map-pairs()
  • fn:outermost()
  • fn:parse-xml()
  • fn:parse-xml-fragment()
  • fn:path()
  • fn:serialize()
  • fn:tail()
  • fn:unparsed-text()
  • fn:unparsed-text-available()
  • fn:unparsed-text-lines()
  • fn:uri-collection()

New signatures have been added for the following functions:

  • fn:document-uri() with 0 arguments
  • fn:string-join() with 1 argument
  • fn:node-name() with 0 arguments
  • fn:round() with 2 arguments
  • fn:data() with 0 arguments

Changelog

Version 7.3
  • Added: Simple map operator
Version 7.2
  • Added: Annotations
  • Updated: EQName syntax
Version 7.1
  • Added: Expanded QNames, Computed Namespace Constructor
Version 7.0
  • String Concatenator