[xquery-talk] creating tree from sequence (from tree)
G. Ken Holman
gkholman at CraneSoftwrights.com
Sat May 7 06:11:42 PDT 2011
At 2011-05-07 09:03 -0400, I wrote:
>I took it as a challenge to use an arbitrary node set as you posited.
The solution below might run a bit faster than my earlier solution
... I was checking ancestors and descendants at every level for the
given node, when I need only exclude the given node from the set of
ancestors and descendants.
I hope this helps.
. . . . . . . . Ken
T:\ftemp>type t.xml
<?xml version="1.0" encoding="UTF-8"?>
<root>
<foo>
<bar>one</bar>
<foo>
<bar>two</bar>
</foo>
<foo>
<bar>three</bar>
</foo>
</foo>
<foo>
<bar>four</bar>
<foo>
<foo>
<bar>five</bar>
</foo>
</foo>
</foo>
</root>
T:\ftemp>xquery t.xq
<?xml version="1.0" encoding="UTF-8"?>
<bar>one<bar>two</bar>
<bar>three</bar>
</bar>
<bar>four<bar>five</bar>
</bar>
T:\ftemp>type t.xq
declare function local:generate-id( $node as node() ) as xs:string
{
(:replace this in the future with a standard implementation of generate-id:)
concat('N',count($node/preceding::node()))
};
declare function local:outDescendants( $nodes as node()* ) as node()*
{
let $nodeIds := $nodes/local:generate-id(.)
for $node in $nodes return
let $ancestors :=
($node/ancestor::*/* except $node)[local:generate-id(.) = $nodeIds]
let $descendants :=
($node/..//* except $node)[local:generate-id(.) = $nodeIds]
return if ( $ancestors )
then () (:this node has already been handled:)
else if ( $descendants )
then (:this node's descendants are in the list:)
element { local-name($node) }
{
( $node/text(),
local:outDescendants( $descendants )
)
}
else (:this is a leaf node and belongs in the result:)
$node
};
let $nodes:= doc('t.xml')//foo/bar
return local:outDescendants( $nodes )
T:\ftemp>
--
Contact us for world-wide XML consulting & instructor-led training
Crane Softwrights Ltd. http://www.CraneSoftwrights.com/q/
G. Ken Holman mailto:gkholman at CraneSoftwrights.com
Legal business disclaimers: http://www.CraneSoftwrights.com/legal
More information about the talk
mailing list