xquery version "3.1";
(:~
: represant sequence of path strings as sequence of xml trees
:)
module namespace tree = 'quodatum.data.tree';
(:~
: convert path(s) to tree
:)
declare function tree:build($paths as xs:string*,$del as xs:string)
{
fn:fold-right($paths,
(),
function($this,$acc){ tree:merge($acc,tree:nest($this,$del)) }
)
};
(:~ convert a path to xml :)
declare function tree:nest($path as xs:string,$del as xs:string)
as element(*)
{
let $path:=if(starts-with($path,$del)) then $path else $del || $path
let $parts:=fn:tokenize(($path),"\" || $del)
return fn:fold-right(subsequence($parts,1,count($parts)-1),
,
tree:wrap#2
)
};
declare function tree:wrap($this as xs:string,$acc)
as element(*)
{
{$acc}
};
declare function tree:merge($a1 as element(*)?,$a2 as element(*)?)
as element(*)*
{
if($a1/@name=$a2/@name) then
let $n1:=$a1/*
let $n2:=$a2/*
let $t:=(
for $x in fn:distinct-values($n1/@name[.=$n2/@name]) (:both:)
return tree:merge($a1/*[@name=$x],$a2/*[@name=$x]),
for $x in fn:distinct-values($n1/@name[fn:not(.=$n2/@name)]) (:only $a1 :)
return $a1/*[@name=$x],
for $x in fn:distinct-values($n2/@name[fn:not(.=$n1/@name)]) (:only $a2 :)
return $a2/*[@name=$x]
)
return tree:wrap($a1/@name,for $x in $t order by $x/@name return $x)
else
($a1,$a2)
};