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. Advertising

  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. Advertising

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,497
    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:
    541
    =?Utf-8?B?ZGhucml2ZXJzaWRl?=
    May 20, 2005
  3. Replies:
    2
    Views:
    362
    Joe Kesselman
    Apr 17, 2006
  4. Stub

    B tree, B+ tree and B* tree

    Stub, Nov 12, 2003, in forum: C Programming
    Replies:
    3
    Views:
    10,109
  5. Replies:
    5
    Views:
    461
    Luc The Perverse
    Oct 27, 2006
Loading...

Share This Page