Difference between revisions of "XQuery Recipes"
m (Text replacement - "syntaxhighlight" to "pre") |
|||
(3 intermediate revisions by the same user not shown) | |||
Line 8: | Line 8: | ||
* 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: | * 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: | ||
− | < | + | <pre lang='xquery'> |
let $s := "X" return ( | let $s := "X" return ( | ||
(: OLD :) if(count($s) = 1) then 'OK' else (), | (: OLD :) if(count($s) = 1) then 'OK' else (), | ||
(: NEW :) $s ! 'OK' | (: NEW :) $s ! 'OK' | ||
) | ) | ||
− | </ | + | </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 19: | Line 19: | ||
* If you want to choose the first non-empty item from two arguments, we can use the position predicate: | * If you want to choose the first non-empty item from two arguments, we can use the position predicate: | ||
− | < | + | <pre lang='xquery'> |
let $s := "X" return ( | let $s := "X" return ( | ||
(: OLD :) if(exists($s)) then $s else 'default', | (: OLD :) if(exists($s)) then $s else 'default', | ||
(: NEW :) ($s, 'default')[1] | (: NEW :) ($s, 'default')[1] | ||
) | ) | ||
− | </ | + | </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 30: | Line 30: | ||
== Computed Elements == | == Computed Elements == | ||
Returns dynamically named elements: | Returns dynamically named elements: | ||
− | < | + | <pre lang='xquery'> |
let $root := "element" | let $root := "element" | ||
let $value := "hi" | let $value := "hi" | ||
Line 37: | Line 37: | ||
attribute { "about" } { $value }, $contents | attribute { "about" } { $value }, $contents | ||
} | } | ||
− | </ | + | </pre> |
The result is an XML fragment with <code><element></code> as root node: | The result is an XML fragment with <code><element></code> as root node: | ||
− | < | + | <pre lang="xml"> |
<element about="hi"> | <element about="hi"> | ||
<foo>Bar!</foo> | <foo>Bar!</foo> | ||
</element> | </element> | ||
− | </ | + | </pre> |
== Transform List to Tree == | == Transform List to Tree == | ||
This snippet transform a ''flat'' list of elements with <code>parentId</code>-references to a nested list. | This snippet transform a ''flat'' list of elements with <code>parentId</code>-references to a nested list. | ||
− | < | + | <pre lang='xquery'> |
declare function local:link($entries as node()*, $id as xs:string) { | declare function local:link($entries as node()*, $id as xs:string) { | ||
let $entry := $entries[@id eq $id], | let $entry := $entries[@id eq $id], | ||
Line 71: | Line 71: | ||
</entries> | </entries> | ||
return local:link($entries/entry, 'entry1') | return local:link($entries/entry, 'entry1') | ||
− | </ | + | </pre> |
results in | results in | ||
− | < | + | <pre lang="xml"> |
<entry id="entry1"> | <entry id="entry1"> | ||
<entry id="entry2" parentId="entry1"> | <entry id="entry2" parentId="entry1"> | ||
Line 84: | Line 84: | ||
</entry> | </entry> | ||
</entry> | </entry> | ||
− | </ | + | </pre> |
== IP-Converter == | == IP-Converter == | ||
Line 90: | Line 90: | ||
This snippet converts an IP address to its numeric representation: | This snippet converts an IP address to its numeric representation: | ||
− | < | + | <pre lang='xquery'> |
let $ip := '134.34.226.65' | let $ip := '134.34.226.65' | ||
return fold-left( | return fold-left( | ||
Line 97: | Line 97: | ||
function($n, $d) { 256 * $n + $d } | function($n, $d) { 256 * $n + $d } | ||
) | ) | ||
− | </ | + | </pre> |
results in | results in | ||
− | < | + | <pre lang="xml"> |
2250433089 | 2250433089 | ||
− | </ | + | </pre> |
== Count number of files == | == Count number of files == | ||
− | This snippets returns the number of JPG files in a directory and its | + | This snippets returns the number of JPG files in a directory and its subdirectories: |
− | < | + | <pre lang='xquery'> |
− | basex "count(file:list('.',true(),'*.jpg'))"</ | + | basex "count(file:list('.',true(),'*.jpg'))"</pre> |
The Linux equivalent is | The Linux equivalent is | ||
− | < | + | <pre lang="xml"> |
find . | grep \.jpg$ | wc -l | find . | grep \.jpg$ | wc -l | ||
− | </ | + | </pre> |
Latest revision as of 18:38, 1 December 2023
This page contains code snippets that mainly originate from our basex-talk mailing list.
Contents
Compact Notations[edit]
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[edit]
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:
<element about="hi">
<foo>Bar!</foo>
</element>
Transform List to Tree[edit]
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
<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[edit]
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
2250433089
Count number of files[edit]
This snippets returns the number of JPG files in a directory and its subdirectories:
basex "count(file:list('.',true(),'*.jpg'))"
The Linux equivalent is
find . | grep \.jpg$ | wc -l