XQuery Recipes

This page contains code snippets that mainly originate from our basex-talk mailing list.

Compact Notations
/ / constructs can look pretty verbose in XQuery. However, some alternatives exist in order to make conditional code more compact:


 * The Simple Map Operator can be used to trigger an action if a value has a single item. The following two expressions are equivalent:

 let $s := "X" return ( (: OLD :) if(count($s) = 1) then 'OK' else,  (: NEW :) $s ! 'OK' )

In some cases, also the first solution can be written more compact. If we know that our input will always have 0-1 items, we can write. If our input will never be an empty string, a zero, etc, it’s sufficient to write.


 * If you want to choose the first non-empty item from two arguments, we can use the position predicate:

 let $s := "X" return ( (: OLD :) if(exists($s)) then $s else 'default',  (: NEW :) ($s, 'default')[1] )

Note that this only works if both of your inputs have zero or one items.

Computed Elements
Returns dynamically named elements:  let $root := "element" let $value := "hi" let $contents := Bar! return element { $root } { attribute { "about" } { $value }, $contents }

The result is an XML fragment with  as root node:  Bar!

Transform List to Tree
This snippet transform a flat list of elements with -references to a nested list.

 declare function local:link($entries as node*, $id as xs:string) { let $entry   := $entries[@id eq $id], $children := $entries[@parentId eq $id] return element entry { $entry/@*, for $child in $children return local:link($entries, $child/@id) } };

let $entries :=       return local:link($entries/entry, 'entry1') results in      <entry id="entry6" parentId="entry3"/> <entry id="entry7" parentId="entry3"/>

IP-Converter
This snippet converts an IP address to its numeric representation:

<pre class="brush:xquery"> let $ip := '134.34.226.65' return fold-left(  tokenize($ip, '\.')!xs:integer(.),   0,  function($n, $d) { 256 * $n + $d } ) results in <pre class="brush:xml"> 2250433089

Count number of files
This snippets returns the number of JPG files in a directory and its sub-directories:

<pre class="brush:xquery"> basex "count(file:list('.',true,'*.jpg'))"

The Linux equivalent is

<pre class="brush:xml"> find. | grep \.jpg$ | wc -l