Skip to content

Instantly share code, notes, and snippets.

@joewiz
Last active June 10, 2020 16:43
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save joewiz/906c7d3248c09a07407d91b73dfd7fe0 to your computer and use it in GitHub Desktop.
Save joewiz/906c7d3248c09a07407d91b73dfd7fe0 to your computer and use it in GitHub Desktop.
An implementation of XQuery 3.1's map:find function for eXist
xquery version "3.1";
(:~
: An implementation of XQuery 3.1's map:find function for eXist, which does not support it natively as of 3.4.0.
:
: @author Joe Wicentowski
: @see https://www.w3.org/TR/xpath-functions-31/#func-map-find
:)
module namespace mf="http://joewiz.org/ns/xquery/map-find";
(:~
: Searches the supplied input sequence and any contained maps and arrays for a map entry with the supplied key, and returns the corresponding values.
: @param $input An input sequence
: @param $key A key
: @returns An array containing the value of any entries found to have the key
: @see https://www.w3.org/TR/xpath-functions-31/#func-map-find
:)
declare function mf:map-find($input as item()*, $key as xs:anyAtomicType) as array(*) {
array { mf:map-find-recurse($input, $key) }
};
(:~
: A utility function that recurses through the input searching for map entries with the supplied key.
: @param $input An input sequence
: @param $key A key
: @return The value of any entries found to have the key
:)
declare %private function mf:map-find-recurse($input as item()*, $key as xs:anyAtomicType) as item()* {
for $i in $input
return
if ($i instance of array(*)) then
mf:map-find-recurse($i?*, $key)
else if ($i instance of map(*)) then
map:for-each($i,
function($k, $v) {
if ($k eq $key) then
$v
else
(),
mf:map-find-recurse($v, $key)
}
)
else ()
};
xquery version "3.1";
import module namespace mf="http://joewiz.org/ns/xquery/map-find" at "map-find.xqm";
(:~
: Tests for mf:map-find, drawn from examples in the XPath & XQuery 3.1 F&O spec for map:find
:
: @author Joe Wicentowski
: @see https://www.w3.org/TR/xpath-functions-31/#func-map-find
:)
let $responses :=
[
map {
0: "no",
1: "yes"
},
map {
0: "non",
1: "oui"
},
map {
0: "nein",
1: ("ja","doch")
}
]
let $inventory :=
map {
"parts": [
map {
"parts": [],
"name": "engine",
"id": "YW678"
}
],
"name": "car",
"id": "QZ123"
}
return
(
mf:map-find($responses, 0),
mf:map-find($responses, 1),
mf:map-find($responses, 2),
mf:map-find($inventory, "parts")
)
xquery version "3.1";
[
["no","non","nein"],
["yes","oui","ja","doch"],
[],
[
[
map {
"parts": [],
"name": "engine",
"id": "YW678"
}
],
[]
]
]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment