59 lines
1.5 KiB
Text
59 lines
1.5 KiB
Text
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),
|
|
<file name="{$parts[last()]}" target="{$path}"/>,
|
|
tree:wrap#2
|
|
)
|
|
};
|
|
|
|
declare function tree:wrap($this as xs:string,$acc)
|
|
as element(*)
|
|
{
|
|
<directory name="{$this}">{$acc}</directory>
|
|
};
|
|
|
|
|
|
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)
|
|
};
|
|
|