Jump to content

XQuery/Gotchas

From Wikibooks, open books for an open world

generalised equals

[edit | edit source]

= is a sequence comparison which is true if the intersection is not empty. Thus:

(1, 2, 3) = (3, 4, 5)

and

 3 = (3, 4, 5)

but there are some oddities. For example

 () = ()

is false, as is

 () != ()

The operator eq is used to compare values only.

Arithmetic operators

[edit | edit source]

The minus sign needs space around it since $x-3 is a valid variable name which is not the same as $x - 3.

Matching brackets etc

[edit | edit source]

Check carefully for matching single and double quotes, round and square brackets and curly braces. The java client will show the matching bracket, but errors are often poorly diagnosed by XQuery compilers.


Binding

[edit | edit source]
:= is the binding operator.

The abbreviated form in which multiple binding statements can be separated by a comma:

 let $x := 3
 let $y := 4
 let $x := "fred"
          

Abbreviates to

 let $x := 3,
     $y := 4,
     $x := "fred"


is convenient but can lead to errors when code is amended. Consider avoiding this syntax.

Conditional expression

[edit | edit source]

The conditional expression must have the else part. Return the empty sequence () if one alternative is not required:

if ($x = 4) 
then "Four"
else ()

Sorting

[edit | edit source]

'Order by' sorts numbers as text

  order by $c/population

To get it sorted as a number, you have to use the number() function

  order by number($C/population)

or cast to a number type

  order by xs:integer($c/population)   

or

  order by $c/population cast as xs:integer

XML construction

[edit | edit source]

You can build XML by simply starting a tag. These tags are really XQuery expression operators. However, this puts you in a lexical scope where everything is XML and curly braces then switch back to normal XQuery (and an open tag will then switch back to XML). Escape curly braces with double braces ({{ }}).

Note the toggling between XQuery and XML construction modes:

 let $a:= "bob"
 let $b:= "jane"
 let $ab := ($a, $b)
 return 
   <people>
   { for $person in $ab
     return <person> {$person} </person>
   }
   </people>

Comments

[edit | edit source]

Comments in XQuery use (: ... :) whereas comments in XML use <!-- ... -->

It is easy to use the wrong kind in the wrong context, particularly XQuery comments in constructed XML.

<A> (: a comment :) </A>

makes the comment the text part of an XML element.

let statements are part of a FLWOR expression and can't appear alone. XQuery is a functional language and let statements are only temporary bindings of names to expressions.

let $x := 5
return $x

function result

[edit | edit source]

return is not required in functions. It is part of a FLWOR statement and not a statement in itself (like let). So it is not required and not allowed if there is no for or let.

 declare function local:sum($a, $b) {
   $a + $b
 }

or

declare function local:sum($a, $b) {
   let $c := $a + $b
   return $c
 }
 

but not

 declare function local:sum($a, $b) {
   return $a + $b
 }

Rounding with double and floats

[edit | edit source]

You might be surprised at that the result of the following:

number(3.1) + number(3.2)

is 6.30000000000001 This is because number() casts the values to double and the double precision numbers round values using an algorithm that is statistically close when using many numbers but fails in specific test cases like this. This is not technically an error and other systems (Scala, ruby, python etc.) will also generate the same errors. The way around this is to not use the number() function, but cast to an xs:decimal().

xs:decimal(3.1) + xs:decimal(3.2)