[xquery-talk] reproducing nested structure
trubliphone
trubliphone at googlemail.com
Sun Mar 13 10:00:37 PST 2011
Hello,
I have managed to write some code to reproduce the nested structure of
a source document (once that document has gone out of context), but it
is _really_ ugly. I was wondering if anybody has any suggestions on
improving it.
Assume the documents look like this:
<one>
<two foo="bar">
<three foo="bar">
<four/>
</three>
<four foo="bar">
<five foo="bar"/>
</four>
<six>
</two>
</one>
There is another configuration file that describes (in XPath) the
"facets" that I want to select on:
<facet name="bar">//node()[@foo='bar']</facet>
So it is trivial to return all of the matching facets in a structure like this:
<two foo="bar"/>
<three foo="bar/">
<four foo="bar"/>
<five foo="bar"/>
But what I want to produce is something that preserves their nested
structure, like this:
<two foo="bar">
<three foo="bar"/>
<four foo="bar">
<five foo="bar"/>
</four>
</two>
Here is the xquery code I came up with:
$document := myCurrentDocument.xml
$configFile := myConfigFile.xml
for $facet in $configFile//facet
let $query := data($facet)
let $value := util:eval(concat('$document/",$query))
(: this returns a sequence of facets with the depth of each one as
an attribute :)
(: I do this to reproduce the potential nested structure of facets :)
let $completeFacets :=
for $v in $value
let $depth := $v/count(ancestor::node())
return
element subFacet {
attribute depth { $depth },
$v
}
return := nestFacets(1,$completeFacets)
};
declare function nestFacets($i as xs:integer, $facets as node()*) {
let $j := ($i + 1)
let $facet := $facets[$i]
let $nextFacet := $facets[$j]
let $hasNext := $nextFacet instance of element()
let $facetValue := $facet/child::node()
return
if ($i <= count($facets)) then (
if ($hasNext) then (
if ($nextFacet/@depth > $facet/@depth) then (
<facet>
{
$facetValue,
(: recurse before closing this element :)
nestFacets($j,$facets)
}
</facet>
)
else (
<facet>
{
$facetValue
}
</facet>,
(: recurse after closing this element :)
nestFacets($j,$facets)
)
)
else (
(: don't recurse :)
<facet>{$facetValue}</facet>
)
)
else ()
};
This will return a structure like this:
<facet>
<two foo="bar"/>
<facet>
<three foo="bar"/>
</facet>
<facet>
<four foo="bar"/>
<facet>
<five foo="bar"/>
</facet>
</facet>
</facet>
Surely there is a better way to do this?
Thanks for your advice.
More information about the talk
mailing list