[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