[xquery-talk] creating tree from sequence (from tree)
G. Ken Holman
gkholman at CraneSoftwrights.com
Sat May 7 05:16:17 PDT 2011
At 2011-05-06 16:29 -0700, trubliphone wrote:
>I have an algorithmic problem I haven't been able to solve. I was
>hoping somebody on this list could offer me some advice.
>
>Suppose I have some arbitrary XML file:
Given the nested in this file, I was immediately drawn to using XSLT
and not XQuery. After solving the problem very succinctly in XSLT,
that guided me in the writing of an XQuery solution.
>Now, suppose there is a user-provided XPath expression to find
>particular nodes in that file:
>
>$query := "//foo/bar"
My solution is not so parameterized because neither XSLT nor XQuery
have an eval() that would allow such an XPath expression to be
dynamically evaluated as either a select expression or a match
expression. Plus, I think starting at the bar elements presupposes
an inefficient pull-style solution rather than a push-style solution.
So you can ignore my answer if you wish, but for a push-style
solution, please see the code below.
>My question is how to turn that into a tree that recreates the
>original hierarchical structure?
I think it is more efficient to work from the original hierarchical
structure and create the tree that you need.
I hope you find the solutions below helpful.
. . . . . . . . . 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:match( $nodes as node()* ) as node()*
{
for $node in $nodes return
typeswitch( $node )
case element(foo) return if( $node/bar )
then <bar>
{local:match(($node/bar/node(),$node/foo))}
</bar>
else local:match( $node/foo )
default return if( $node/self::text()/parent::bar ) then $node else ()
};
local:match( doc('t.xml')/root/* )
T:\ftemp>xslt t.xml t.xsl
<?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.xsl
<?xml version="1.0" encoding="US-ASCII"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:template match="root/text() | foo/text()"/>
<xsl:template match="foo[bar]">
<bar>
<xsl:apply-templates select="bar/node()"/>
<xsl:apply-templates select="foo"/>
</bar>
</xsl:template>
</xsl:stylesheet>
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