Difference between revisions of "XQuery Recipes"
(13 intermediate revisions by 3 users not shown) | |||
Line 1: | Line 1: | ||
This page contains code snippets that mainly originate from our [https://mailman.uni-konstanz.de/mailman/listinfo/basex-talk basex-talk] mailing list. | This page contains code snippets that mainly originate from our [https://mailman.uni-konstanz.de/mailman/listinfo/basex-talk basex-talk] mailing list. | ||
+ | |||
+ | == Compact Notations == | ||
+ | |||
+ | <code>if</code>/<code>not</code>/<code>else</code> constructs can look pretty verbose in XQuery. | ||
+ | However, some alternatives exist in order to make conditional code more compact: | ||
+ | |||
+ | * The [[XQuery 3.0#Simple Map Operator|Simple Map Operator]] can be used to trigger an action if a value has a single item. The following two expressions are equivalent: | ||
+ | |||
+ | <syntaxhighlight lang="xquery"> | ||
+ | let $s := "X" return ( | ||
+ | (: OLD :) if(count($s) = 1) then 'OK' else (), | ||
+ | (: NEW :) $s ! 'OK' | ||
+ | ) | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | 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>. | ||
+ | |||
+ | * If you want to choose the first non-empty item from two arguments, we can use the position predicate: | ||
+ | |||
+ | <syntaxhighlight lang="xquery"> | ||
+ | let $s := "X" return ( | ||
+ | (: OLD :) if(exists($s)) then $s else 'default', | ||
+ | (: NEW :) ($s, 'default')[1] | ||
+ | ) | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Note that this only works if both of your inputs have zero or one items. | ||
== Computed Elements == | == Computed Elements == | ||
Returns dynamically named elements: | Returns dynamically named elements: | ||
− | < | + | <syntaxhighlight lang="xquery"> |
− | let $ | + | let $root := "element" |
− | let $contents :=<foo | + | let $value := "hi" |
− | return element { $ | + | let $contents := <foo>Bar!</foo> |
− | attribute { "about" } { $ | + | return element { $root } { |
+ | attribute { "about" } { $value }, $contents | ||
} | } | ||
− | </ | + | </syntaxhighlight> |
− | The result is an element | + | |
− | < | + | The result is an XML fragment with <code><element></code> as root node: |
− | < | + | <syntaxhighlight lang="xml"> |
− | < | + | <element about="hi"> |
− | < | + | <foo>Bar!</foo> |
− | </ | + | </element> |
− | </ | + | </syntaxhighlight> |
+ | |||
+ | == Transform List to Tree == | ||
+ | This snippet transform a ''flat'' list of elements with <code>parentId</code>-references to a nested list. | ||
+ | |||
+ | <syntaxhighlight lang="xquery"> | ||
+ | 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') | ||
+ | </syntaxhighlight> | ||
+ | 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> | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | == IP-Converter == | ||
+ | |||
+ | This snippet converts an IP address to its numeric representation: | ||
+ | |||
+ | <syntaxhighlight lang="xquery"> | ||
+ | let $ip := '134.34.226.65' | ||
+ | return fold-left( | ||
+ | tokenize($ip, '\.')!xs:integer(.), | ||
+ | 0, | ||
+ | function($n, $d) { 256 * $n + $d } | ||
+ | ) | ||
+ | </syntaxhighlight> | ||
+ | results in | ||
+ | <syntaxhighlight lang="xml"> | ||
+ | 2250433089 | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | == Count number of files == | ||
+ | |||
+ | This snippets returns the number of JPG files in a directory and its sub-directories: | ||
+ | |||
+ | <syntaxhighlight lang="xquery"> | ||
+ | basex "count(file:list('.',true(),'*.jpg'))"</syntaxhighlight> | ||
+ | |||
+ | The Linux equivalent is | ||
− | + | <syntaxhighlight lang="xml"> | |
+ | find . | grep \.jpg$ | wc -l | ||
+ | </syntaxhighlight> |
Revision as of 14:23, 27 February 2020
This page contains code snippets that mainly originate from our basex-talk mailing list.
Contents
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:
<syntaxhighlight lang="xquery"> let $s := "X" return (
(: OLD :) if(count($s) = 1) then 'OK' else (), (: NEW :) $s ! 'OK'
) </syntaxhighlight>
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:
<syntaxhighlight lang="xquery"> let $s := "X" return (
(: OLD :) if(exists($s)) then $s else 'default', (: NEW :) ($s, 'default')[1]
) </syntaxhighlight>
Note that this only works if both of your inputs have zero or one items.
Computed Elements
Returns dynamically named elements: <syntaxhighlight lang="xquery"> let $root := "element" let $value := "hi" let $contents := <foo>Bar!</foo> return element { $root } {
attribute { "about" } { $value }, $contents
} </syntaxhighlight>
The result is an XML fragment with <element>
as root node:
<syntaxhighlight lang="xml">
<element about="hi">
<foo>Bar!</foo>
</element> </syntaxhighlight>
Transform List to Tree
This snippet transform a flat list of elements with parentId
-references to a nested list.
<syntaxhighlight lang="xquery"> 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') </syntaxhighlight> 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> </syntaxhighlight>
IP-Converter
This snippet converts an IP address to its numeric representation:
<syntaxhighlight lang="xquery"> let $ip := '134.34.226.65' return fold-left(
tokenize($ip, '\.')!xs:integer(.), 0, function($n, $d) { 256 * $n + $d }
) </syntaxhighlight> results in <syntaxhighlight lang="xml"> 2250433089 </syntaxhighlight>
Count number of files
This snippets returns the number of JPG files in a directory and its sub-directories:
<syntaxhighlight lang="xquery"> basex "count(file:list('.',true(),'*.jpg'))"</syntaxhighlight>
The Linux equivalent is
<syntaxhighlight lang="xml"> find . | grep \.jpg$ | wc -l </syntaxhighlight>