|  | Home · All Classes · Main Classes · Grouped Classes · Modules · Functions |

# A Short Path to XQuery

- Introduction
- Atomic Values

- Using Atomic Values

- More Node Constructors
- Further Reading
- FAQ

- Path expressions misses
- Variable in for loop is out of scope

### Introduction

While languages such as Java and C++ are largely made of statements, XQuery has expressions at its core. There is a plethora of expressions available ranging from sorting to function calls, but one of the simplest are direct node constructors, like this one:

     <myElement/>

This is an XQuery query, and it also happens to be a well-formed XML document. All the usual types of nodes that can be found in an XML document can be used as expressions in XQuery, and one can go ahead and embed other expressions inside them, by using curly braces:

     (: Copy the value of xml:id attribute from other.html. This is a comment by the way! :)
     <html xmlns="http://www.w3.org/1999/xhtml/"
           xml:id="{doc("other.html")/html/@xml:id}"/>

### Atomic Values

Apart from nodes, XQuery has atomic values and they are just what one would think they are: small, primitive values. Here's a run down of some of the most common:

Name | Description
--- | ---
`xs:integer` | A 64 bit integer
`xs:boolean` | A boolean value, `false` or `true`
`xs:double` | A 64 bit floating point value
`xs:string` | A string where each codepoint is an XML 1.0 character(essentially Unicode)
`xs:date` | A date, such as when you're born: `1984-10-15`
`xs:time` | A time, such as when you show up at work: `09:00:00`
`xs:dateTime` | A date followed by a time: 1984-10-15T05:00:00
`xs:duration` | A time interval such as P5Y2M10DT15H, which represents five years, two months, 10 days, and 15 hours.
`xs:base64Binary` | Represents data, possibly binary data, in Base 64 encoding.

Integers, doubles and strings can be created by using literal expressions, booleans with the functions `true()` or `false()` (just `true` or `false` would be name tests), and for the rest constructor functions must be used. Here's a query illustrating this, which evaluates to a sequence of mixed atomic values:

     declare variable $date := fn:current-date(); (: This line should not be part of the example. It exists in order to make the query valid. :)
     fn:current-date() - $date > xs:dayTimeDuration("P365D")

Each atomic type can construct a value from a string. While doing so it validates the input string to ensure it has a proper format and if not, it issues a query error. These formats tend to be as one would guess it to be. For instance, if one passes "1.five" to `xs:decimal`'s constructor, as opposed to "1.5" it will halt the query such that the bug can be corrected.

In the example an `xs:boolean` was created from an `xs:integer` as opposed to from a string, and that's because values doesn't have to be constructed from strings, they can be created, or converted, from a range of different types. For instance, an `xs:double` can be created from a `xs:decimal`, or a `xs:boolean` can be converted to an `xs:string`. What conversions that are possible depends on the types but they tend to be intuitive. One of the specifications has a nifty table outlining those.

#### Using Atomic Values

Once atomic values have been constructed, via one of the methods mentioned above, or as return values from functions or by evaluating variables, one can pass them along to functions, convert them to strings and attach them as part of text nodes to nodes, or use operators between them. Let's look at the latter.

Apart from the usual arithmetic operators between numbers one would expect, they are also available between more exotic types. Have a look at this query:

It substracts two dates which returns an `xs:dayTimeDuration`, which it subsequently compares against another `:xs:dayTimeDuration`. The query finally evaluates to a single atomic value of type `xs:boolean`.

The available operators and between what types are summarized in a table in the main XQuery specification.

### More Node Constructors

### Further Reading

XQuery is a big language that is hard to cover in an overview. If one wants a good understanding of the subject, a good thing could be to get a book on topic, in the same manner that one has a book on C++.

Another alternative is to ask a question or two on the mailing lists qt-interest or talk on x-query.com.

Of course, the specifications is one alternative, but one has to take a deep breath before diving into those. Here are the links to (some of) them:

- XQuery 1.0 and XPath 2.0 Functions and Operators describes all the builtin functions, and how conversions between atomic values are done.
- XQuery 1.0: An XML Query Language is the main specification that describes the syntax and behavior.

### FAQ

#### Path expressions misses

Often this is caused by that the names that the axis step matches, is different from nodes being matched. For instance, let's say that `index.html` in this query:

     (: Select all paragraphs that contains examples. :)
     doc("index.html")/html/body/p[@class="example"]

is an XHTML document and hence it resides in the namespace `http://www.w3.org/1999/xhtml/`. The path won't match since they look for ``html and so forth, while the actual name is `\{http://www.w3.org/1999/xhtml/\}html`. The fix is straight forward:

     declare namespace x = "http://www.w3.org/1999/xhtml/";
     (: Select all paragraphs that contains examples. :)
     doc("index.html")/x:html/x:body/x:p[@class="example"]

Path expressions also pick up the default namespace if one is declared:

     declare default element namespace "http://www.w3.org/1999/xhtml/";
     <html>
         <body>
             {
                 for $i in doc("testResult.xml")/tests/test[@status = "failure"]
                 order by $i/@name
                 return <p>{$i/@name}</p>
             }
         </body>
     </html>

In this case the nodes created by the direct element constructors will be in the XHTML namespace, but so will the path expressions. Hence they look for `\{http://www.w3.org/1999/xhtml/\}tests` and so forth, while `testResult.xml` is perhaps in a different namespace, or no namespace at all.

#### Variable in for loop is out of scope

Due to expression precedence it might be necessary to wrap the `return` expression in a `for` clause with paranteses:

     for $i in(reverse(1 to 10)),
         $d in xs:integer(doc("numbers.xml")/numbers/number)
     return ($i + $d)

Without the paranteses on the last line, the arithmetic expression would have had the whole `for` clause as it left operand, and since the scope of variable `$d` ends at the `return` clause, the variable reference would be out of scope.