Difference between revisions of "XQuery Recipes"

From BaseX Documentation
Jump to navigation Jump to search
m (Text replacement - "<syntaxhighlight lang="xquery">" to "<pre lang='xquery'>")
Tags: Mobile web edit Mobile edit
m (Text replacement - "</syntaxhighlight>" to "</pre>")
Line 13: Line 13:
 
   (: NEW :) $s ! 'OK'
 
   (: NEW :) $s ! 'OK'
 
)
 
)
</syntaxhighlight>
+
</pre>
  
 
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 <code>if(exists($s))</code>. If our input will never be an empty string, a zero, etc, it’s sufficient to write <code>if($s)</code>.
 
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 <code>if(exists($s))</code>. If our input will never be an empty string, a zero, etc, it’s sufficient to write <code>if($s)</code>.
Line 24: Line 24:
 
   (: NEW :) ($s, 'default')[1]
 
   (: NEW :) ($s, 'default')[1]
 
)
 
)
</syntaxhighlight>
+
</pre>
  
 
Note that this only works if both of your inputs have zero or one items.
 
Note that this only works if both of your inputs have zero or one items.
Line 37: Line 37:
 
   attribute { "about" } { $value }, $contents
 
   attribute { "about" } { $value }, $contents
 
}
 
}
</syntaxhighlight>
+
</pre>
  
 
The result is an XML fragment with <code>&lt;element&gt;</code> as root node:
 
The result is an XML fragment with <code>&lt;element&gt;</code> as root node:
Line 44: Line 44:
 
   <foo>Bar!</foo>
 
   <foo>Bar!</foo>
 
</element>
 
</element>
</syntaxhighlight>
+
</pre>
  
 
== Transform List to Tree ==
 
== Transform List to Tree ==
Line 71: Line 71:
 
  </entries>
 
  </entries>
 
return local:link($entries/entry, 'entry1')
 
return local:link($entries/entry, 'entry1')
</syntaxhighlight>
+
</pre>
 
results in
 
results in
 
<syntaxhighlight lang="xml">
 
<syntaxhighlight lang="xml">
Line 84: Line 84:
 
   </entry>
 
   </entry>
 
</entry>
 
</entry>
</syntaxhighlight>
+
</pre>
  
 
== IP-Converter ==
 
== IP-Converter ==
Line 97: Line 97:
 
   function($n, $d) { 256 * $n + $d }
 
   function($n, $d) { 256 * $n + $d }
 
)
 
)
</syntaxhighlight>
+
</pre>
 
results in
 
results in
 
<syntaxhighlight lang="xml">
 
<syntaxhighlight lang="xml">
 
2250433089
 
2250433089
</syntaxhighlight>
+
</pre>
  
 
== Count number of files ==
 
== Count number of files ==
Line 108: Line 108:
  
 
<pre lang='xquery'>
 
<pre lang='xquery'>
basex "count(file:list('.',true(),'*.jpg'))"</syntaxhighlight>
+
basex "count(file:list('.',true(),'*.jpg'))"</pre>
  
 
The Linux equivalent is
 
The Linux equivalent is
Line 114: Line 114:
 
<syntaxhighlight lang="xml">
 
<syntaxhighlight lang="xml">
 
find . | grep \.jpg$ | wc -l
 
find . | grep \.jpg$ | wc -l
</syntaxhighlight>
+
</pre>

Revision as of 18:35, 1 December 2023

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

Compact Notations

if/not/else 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(exists($s)). If our input will never be an empty string, a zero, etc, it’s sufficient to write if($s).

  • 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 := <foo>Bar!</foo>
return element { $root } {
  attribute { "about" } { $value }, $contents
}

The result is an XML fragment with <element> as root node: <syntaxhighlight lang="xml"> <element about="hi">

 <foo>Bar!</foo>

</element>

Transform List to Tree

This snippet transform a flat list of elements with parentId-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 :=
 <entries>
	  <entry id="entry1" />
	  <entry id="entry2" parentId="entry1" />
	  <entry id="entry3" parentId="entry1" />
	  <entry id="entry4" parentId="entry2" />
	  <entry id="entry5" parentId="entry2" />
	  <entry id="entry6" parentId="entry3" />
	  <entry id="entry7" parentId="entry3" />
 </entries>
return local:link($entries/entry, 'entry1')

results in <syntaxhighlight lang="xml"> <entry id="entry1">

 <entry id="entry2" parentId="entry1">
   <entry id="entry4" parentId="entry2"/>
   <entry id="entry5" parentId="entry2"/>
 </entry>
 <entry id="entry3" parentId="entry1">
   <entry id="entry6" parentId="entry3"/>
   <entry id="entry7" parentId="entry3"/>
 </entry>

</entry>

IP-Converter

This snippet converts an IP address to its numeric representation:

let $ip := '134.34.226.65'
return fold-left(
   tokenize($ip, '\.')!xs:integer(.),
   0,
  function($n, $d) { 256 * $n + $d }
)

results in <syntaxhighlight lang="xml"> 2250433089

Count number of files

This snippets returns the number of JPG files in a directory and its subdirectories:

basex "count(file:list('.',true(),'*.jpg'))"

The Linux equivalent is

<syntaxhighlight lang="xml"> find . | grep \.jpg$ | wc -l