xquery version "1.0"; (: : Copyright 2006-2012 The FLWOR Foundation. : : Licensed under the Apache License, Version 2.0 (the "License"); : you may not use this file except in compliance with the License. : You may obtain a copy of the License at : : http://www.apache.org/licenses/LICENSE-2.0 : : Unless required by applicable law or agreed to in writing, software : distributed under the License is distributed on an "AS IS" BASIS, : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. : See the License for the specific language governing permissions and : limitations under the License. :) (:~ : This module provides the functions defined by the JSONiq specification, : chapter 8 (Function Library). JSONiq extends : the XQuery specification to also deal with JSON data natively. See : : http://jsoniq.org/ : : for details. : : This module depends on having the JSONiq feature enabled in Zorba, : i.e., Zorba must be compiled with ZORBA_WITH_JSON. : : @author Ghislain Fourny :) module namespace libjn = "http://jsoniq.org/function-library"; import module namespace jn = "http://jsoniq.org/functions"; declare namespace ver = "http://www.zorba-xquery.com/options/versioning"; declare option ver:module-version "1.0"; (:~ : This function dynamically builds an object, like jn:object, except that : it does not throw an error upon pair collision. Instead, it aggregates them : into an array. : : @param $o A sequence of objects. : @return The accumulated object. :) declare function libjn:accumulate($o as object()*) as object() { {[ $o ]} }; (:~ : This function returns all Objects contained within a JSON item, regardless of : depth. : : @param $i A JSON item. : @return Its descendant objects. :) declare function libjn:descendant-objects($i as json-item()) as object()* { if ($i instance of object()) then ( $i, for $v in libjn:values($i) where $v instance of json-item() return libjn:descendant-objects($v) ) else if ($i instance of array()) then ( for $v in libjn:members($i) where $v instance of json-item() return libjn:descendant-objects($v) ) else () }; (:~ : This function returns all pairs contained within an object, recursively. : : @param $o An object. : @return All direct and indirect descendant pairs. :) declare function libjn:descendant-pairs($o as object()) as object()* { for $k in jn:keys($o) return ( { $k : $o($k) }, if ($o($k) instance of object()) then libjn:descendant-pairs($o($k)) else () ) }; (:~ : Recursively "flatten" a JSON Array, by replacing any arrays with their : members. Equivalent to : : define function jn:flatten($arg as array()) { : for $value in jn:values($arg) : return : if ($value instance of array()) : then jn:flatten($value) : else $value : }; : : @param $a A JSON Array. : @return The flattened version of $a. :) declare function libjn:flatten($a as array()) as item()* { jn:flatten($a) }; (:~ This function returns the intersection of two objects, and aggregates : values corresponding to the same name into an array. : : @param $o A sequence of objects. : @return Their insersection. :) declare function libjn:intersect($o as object()*) as object() { {| let $common-keys := jn:keys($o[1])[ every $object in $o[position() > 1] satisfies jn:keys($object) = . ] for $key in $common-keys let $values := $o($key) return if (count($values) eq 1) then { $key : $values } else { $key : [ $values ] } |} }; (:~ : Returns the members of an Array. : : @param $a A JSON Array. : @return The members of the specified array. :) declare function libjn:members($o as array()) as item()* { jn:members($o) }; (:~ : Creates an object from the specified pairs of another given object. : Specifically, for each name in $names, if the object $o has a pair with : that name, then a copy of that pair is included in the new object. : : @param $o A JSON Object. : @param $names The names of the pairs to copy out of $o and insert into the new object : @return The new object. :) declare function libjn:project($o as object(), $names as xs:string*) as object() { jn:project($o, $names) }; (:~ : This functions returns all values in an Object. : @param $i An object. : @return Its values. :) declare function libjn:values($i as object()) as item()* { for $k in jn:keys($i) return $i($k) };