XSLT to produce subtree of a tree

Discussion in 'XML' started by Martin Bright, Feb 4, 2004.

  1. I am trying to write an XSLT template which creates a subtree of an input
    document, which is a simple tree. For example, the input might be

    <node name="1"/>
    <node name="2">
    <node name="2.1"/>
    <node name="2.2"/>
    </node>
    <node name="3"/>

    I pass the template a parameter "2.2" and it creates the following result
    fragment:

    <node name="2">
    <node name="2.2"/>
    </node>


    There is clearly one inefficient way of doing this:

    <xsl:template match="node[.//node[@name='2.2']]">
    <xsl:copy><xsl:apply-templates/></xsl:copy>
    </xsl:template>

    But it seems a shame to evaluate that XPath expression on each node. There
    ought also to be a recursive way of doing it, like this:

    <xsl:template match="node">
    <xsl:choose>
    <xsl:when test="@name='2.2'"><xsl:copy/></xsl:when>
    <xsl:eek:therwise>
    <xsl:variable name="children"><xsl:apply-templates/></xsl:variable>
    <xsl:if test="$children">
    <xsl:copy><xsl:copy-of select="$children"/></xsl:copy>
    </xsl:if>
    </xsl:eek:therwise>
    </xsl:choose>
    </xsl:template>

    Unfortunately this doesn't work. The reason, AFAICT, is that the Boolean
    value of a result tree fragment is always true, because it always contains a
    hidden root node.

    Can anybody either solve this particular problem of how to tell when a
    result tree fragment is empty, or tell me a better way to approach this?

    Many thanks
    Martin Bright
     
    Martin Bright, Feb 4, 2004
    #1
    1. Advertisements

  2. "Martin Bright" <> wrote in message
    news:Xns948585CFAB16Amartinboojumorguk@138.253.100.85...
    >
    > I am trying to write an XSLT template which creates a subtree of an input
    > document, which is a simple tree. For example, the input might be
    >
    > <node name="1"/>
    > <node name="2">
    > <node name="2.1"/>
    > <node name="2.2"/>
    > </node>
    > <node name="3"/>
    >
    > I pass the template a parameter "2.2" and it creates the following result
    > fragment:
    >
    > <node name="2">
    > <node name="2.2"/>
    > </node>


    First of all, do notice that the source xml document provided in your
    message is not well-formed.

    This transformation:

    <xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:eek:utput omit-xml-declaration="yes" indent="yes"/>

    <xsl:param name="pNodeID" select="2.2"/>

    <xsl:template match="/">
    <xsl:apply-templates select="//node[@name = $pNodeID]"/>
    </xsl:template>

    <xsl:template match="node">
    <xsl:apply-templates select="ancestor::*[last()]" mode="gen">
    <xsl:with-param name="pPath"
    select=".|ancestor::node[position()&lt; last()]" />
    </xsl:apply-templates>
    </xsl:template>

    <xsl:template match="*" mode="gen">
    <xsl:param name="pPath" select="/.."/>

    <xsl:copy>
    <xsl:copy-of select="@*"/>
    <xsl:apply-templates select="$pPath[1]" mode="gen">
    <xsl:with-param name="pPath" select="$pPath[position() > 1]"/>
    </xsl:apply-templates>
    </xsl:copy>
    </xsl:template>
    </xsl:stylesheet>

    when applied on your source.xml (corrected in order to become well-formed):

    <node name="0">
    <node name="1"/>
    <node name="2">
    <node name="2.1"/>
    <node name="2.2"/>
    </node>
    <node name="3"/>
    </node>

    produces the desired result:

    <node name="0">
    <node name="2">
    <node name="2.2"/>
    </node>
    </node>


    Hope this helped.


    Cheers,

    Dimitre Novatchev [XML MVP],
    FXSL developer, XML Insider,

    http://fxsl.sourceforge.net/ -- the home of FXSL
    Resume: http://fxsl.sf.net/DNovatchev/Resume/Res.html
     
    Dimitre Novatchev [MVP], Feb 4, 2004
    #2
    1. Advertisements

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. .pd.
    Replies:
    1
    Views:
    1,561
    Robert Rossney
    Sep 1, 2003
  2. =?Utf-8?B?ZGhucml2ZXJzaWRl?=

    IETreeView - double click opens subtree

    =?Utf-8?B?ZGhucml2ZXJzaWRl?=, May 20, 2005, in forum: ASP .Net
    Replies:
    0
    Views:
    614
    =?Utf-8?B?ZGhucml2ZXJzaWRl?=
    May 20, 2005
  3. Replies:
    2
    Views:
    456
    Joe Kesselman
    Apr 17, 2006
  4. ahogue at theory dot lcs dot mit dot edu

    XPath subtree pattern matching

    ahogue at theory dot lcs dot mit dot edu, Jul 28, 2003, in forum: XML
    Replies:
    2
    Views:
    1,395
    Dimitre Novatchev
    Jul 29, 2003
  5. Matt
    Replies:
    2
    Views:
    1,238
    Joris Gillis
    Nov 2, 2004
  6. Stub

    B tree, B+ tree and B* tree

    Stub, Nov 12, 2003, in forum: C Programming
    Replies:
    3
    Views:
    10,586
  7. Replies:
    5
    Views:
    738
    Luc The Perverse
    Oct 27, 2006
  8. Robert
    Replies:
    1
    Views:
    508
    Pascal J. Bourguignon
    Apr 14, 2008
Loading...