xsl-list
[Top] [All Lists]

Re: XPath and recursion

2003-10-23 01:17:26
Your XPath for a typical recursion of child elements would be:

- to choose any child of a child of a child etc....

descendant-or-self::*

- to choose a specific node name

descendant-or-self::nodeName

e.g. descendant-or-self::foo will select all descendants of the current
context with the name foo.

to put this into a recursive loop you would use the following:

<xsl:for-each select="document/node">
    <xsl:for-each select="descendant-or-self::*>
        ...
    </xsl:for-each>
</xsl:for-each>

The above will first create a node-set of the first node element siblings.
It will then recursively go through each of these and pull out each child of
a child etc... and put them into a node-set.  Through each loop you can then
have it write out the elements and associated attributes for each node in
the set.  Once it is done with this loop it will go back to the next node in
the first for-each loop etc...

The following XML...

<?xml version="1.0" encoding="utf-8" ?>

<?xml-stylesheet type="text/xsl" href="test.xslt" ?>

<document>
    <node foo="afoo1">
        <node foo="afoo2">
            <node foo="afoo3"/>
            <node foo="afoo4"/>
            <node foo="afoo5"/>
        </node>
        <node foo="afoo6">
            <node foo="afoo7"/>
        </node>
    </node>
    <node foo="bfoo1">
        <node foo="bfoo2">
            <node foo="bfoo3"/>
            <node foo="bfoo4">
                <node foo="bfoo5">
                    <node foo="bfoo6"/>
                </node>
                <node foo="bfoo7"/>
            </node>
            <node foo="bfoo8"/>
        </node>
    </node>
    <node foo="cfoo1">
        <node foo="cfoo2">
            <node foo="cfoo3"/>
        </node>
    </node>
</document>


Parsed by the following stylesheet:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xsl:stylesheet [
 <!ENTITY nbsp "&#160;">
]>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
version="1.0" xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:my="urn:my-scripts">
<xsl:template match="/">

    <xsl:for-each select="document/node">
        <xsl:for-each select="descendant-or-self::*">
            <!-- the below for-each loop simply place a 5 dots and a &gt;
and space for each preceding parent node to illustrate the position within
the tree -->
                <xsl:for-each select="ancestor-or-self::*[not(position() =
1)]">.....&gt;&nbsp;</xsl:for-each>
            <!-- end position of node loop -->
            <xsl:value-of select="@foo"/>&nbsp;<xsl:value-of
select="concat('aux', position())"/><br/>
        </xsl:for-each>
        <br/><br/>
    </xsl:for-each>

</xsl:template>
</xsl:stylesheet>


Will produce the following output...

.....> afoo1 aux1
.....> .....> afoo2 aux2
.....> .....> .....> afoo3 aux3
.....> .....> .....> afoo4 aux4
.....> .....> .....> afoo5 aux5
.....> .....> afoo6 aux6
.....> .....> .....> afoo7 aux7


.....> bfoo1 aux1
.....> .....> bfoo2 aux2
.....> .....> .....> bfoo3 aux3
.....> .....> .....> bfoo4 aux4
.....> .....> .....> .....> bfoo5 aux5
.....> .....> .....> .....> .....> bfoo6 aux6
.....> .....> .....> .....> bfoo7 aux7
.....> .....> .....> bfoo8 aux8


.....> cfoo1 aux1
.....> .....> cfoo2 aux2
.....> .....> .....> cfoo3 aux3

Im unclear on how exactly you are determining the value of the 'aux' (aux1,
aux2, etc...) but if it has to do with the position of the node in each
node-set simply use <xsl:value-of select="concat('Aux', position())"/> for
each loop through the node-set.  If this is not the case let me know and I
will try to help you further.

Hope this helps...

Best regards,

M.

----- Original Message ----- 
From: "Jonny Pony" <jonnypony666(_at_)hotmail(_dot_)com>
To: <xsl-list(_at_)lists(_dot_)mulberrytech(_dot_)com>
Sent: Thursday, October 23, 2003 12:31 AM
Subject: [xsl] XPath and recursion


Hi,

I'm pretty new to XPath and I want to achive the following.

I've got an xml-file, something like this:

<?xml version="1.0" encoding="UTF-8"?>
<document>
<node value1="DB Objects">
<node value1="Andreas">
<node value1="Peter">
<node value1="Kempten"/>
<node value1="Ulperting"/>
</node>
<node value1="Muahhh"/>
<node value1="Christoph">
<node value1="Ulperting"/>
<node value1="FrankyBoy">
<node value1="Munich"/>
</node>
</node>
</node>
<node value1="Christoph">
<node value1="Munich"/>
<node value1="FrankyBoy">
<node value1="Kempten"/>
</node>
</node>
<node value1="Frank"/>
</node>
<node value1="Tables">
<node value1="Andreas">
<node value1="Peter">
<node value1="Munich"/>
<node value1="Ulperting"/>
</node>
</node>
...
</node>
</document>

And I want to get an output like this after the xsl transformation:

aux1 = insFld(foldersTree, gFld("DB-Objects"))
    aux2 = insFld(aux1, gFld("Andreas",))
aux3 = insFld(aux2, gFld("Peter"))
aux4 = insFld(aux3, gFld("Kempten"))
aux4 = insFld(aux3, gFld("Ulperting"))
  aux3 = insFld(aux2, gFld("Muahhh"))
aux3 = insFld(aux2, gFld("Christoph"))
aux4 = insFld(aux3, gFld("FrankyBoy"))
aux5 = insFld(aux4, gFld("Munich"))
aux5 = insFld(aux4, gFld("FrankyBoy"))
aux6 = insFld(aux5, gFld("Kempten"))
aux6 = insFld(aux5, gFld("Kempten"))
aux2 = insFld(aux1, gFld("Christoph"))
aux2 = insFld(aux1, gFld("Frank"))
aux3 = insFld(aux2, gFld("Peter"))
aux4 = insFld(aux3, gFld("Ulperting"))
  aux3 = insFld(aux2, gFld("Muahhh"))
aux3 = insFld(aux2, gFld("Christoph"))
aux4 = insFld(aux3, gFld("Ulperting"))
aux4 = insFld(aux3, gFld("FrankyBoy"))
aux5 = insFld(aux4, gFld("Munich"))
aux1 = insFld(foldersTree, gFld("Tables"))
    aux2 = insFld(aux1, gFld("Andreas",))
aux3 = insFld(aux2, gFld("Peter"))
aux4 = insFld(aux3, gFld("Kempten"))
aux3 = insFld(aux2, gFld("Christoph"))
aux4 = insFld(aux3, gFld("Munich"))
aux4 = insFld(aux3, gFld("Ulperting"))

The idea behind that:
if /document has at least a child, write:
   aux1 = insFld(foldersTreeview, gFld( "<xsl:value-of
select="@value1"/>"));
if the child got at least another child,write:
   aux2 = insFld(aux1, gFld("<xsl:value-of select="@value1"/>");
if the child of the child got at least another child,write:
   aux3 = insFld(aux2, gFld("<xsl:value-of select="@value1"/>");
and so on....

I tried to solve this problem for a long time now, but falways failed. Also
the numbering of "aux", the deeper i get into the node-tree, is impossibly
for me. Have no clue how I would do that.


Thanks
Jonny

_________________________________________________________________
5 neue Buddies = 50 FreeSMS. http://messenger-mania.msn.de MSN Messenger
empfehlen und kräftig abräumen!


 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list



<Prev in Thread] Current Thread [Next in Thread>