> I have xml tree like
>
[quoted text clipped - 13 lines]
> <field name="l3"/>
> </root>
Your XML is not well-formed: it's missing a </field> end-tag before the
</root> end-tag.
> The tree could have many levels, I need a for-each to collect all node name
> under current context, the key is the current context could be on any node,
> for example, it could be the "l1", it could be "l2" or node under "l2". I
> tried to use code like
I'm not clear what you want to do, create a node-set of all the @name
attributes of field elements which are descendants of the context
element, or list the @name values. Here is an XSLT script which lists
the values. No need for for-each: use templates.
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output method="text"/>
<xsl:strip-space elements="*"/>
<xsl:template match="field">
<xsl:value-of select="@name"/>
<xsl:text>: </xsl:text>
<xsl:apply-templates select="descendant::field" mode="sub"/>
<xsl:text>
</xsl:text>
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="field" mode="sub">
<xsl:value-of select="@name"/>
<xsl:text> </xsl:text>
</xsl:template>
</xsl:stylesheet>
It's also not clear what you want to do with the element with a stop
value: cease processing, or simply exclude it (and its descendants)
from the recursion?
///Peter

Signature
XML FAQ: http://xml.silmaril.ie/
///Peter
davidw - 27 Sep 2006 05:40 GMT
Hi,
Thanks.
The XML has a type error. It just a fake data to demo what I want.
It seems I didn't express clearly. What I need is from any node, I can get
all names in its subtree, but exclude those with a stop attribute. check
this xml
<field name="n0">
<field name="n1">
<field name="n11">
<field name="n111"/>
<field name="n112"/>
</field>
</field>
<field name="n2" stop="true">
<field name="n21">
<field name="n211"/>
<field name="n212"/>
</field>
<field name="n22"/>
</field>
<field name="n3"/>
</field>
For example, it the current node is n0, I will get
n11,n111,n112,n2,n3 -- it will not go into n2 since it has a stop
if the current node is n2, I should get n21,n211,n212,n22 -- it should not
affected by the stop, since it only filter childnodes with stop attribute.
I get used to use for-each. Is there a way to do that with for-each?
Thanks!
> > I have xml tree like
> >
[quoted text clipped - 54 lines]
>
> ///Peter
davidw - 27 Sep 2006 05:40 GMT
Hi,
Thanks.
The XML has a type error. It just a fake data to demo what I want.
It seems I didn't express clearly. What I need is from any node, I can get
all names in its subtree, but exclude those with a stop attribute. check
this xml
<field name="n0">
<field name="n1">
<field name="n11">
<field name="n111"/>
<field name="n112"/>
</field>
</field>
<field name="n2" stop="true">
<field name="n21">
<field name="n211"/>
<field name="n212"/>
</field>
<field name="n22"/>
</field>
<field name="n3"/>
</field>
For example, it the current node is n0, I will get
n11,n111,n112,n2,n3 -- it will not go into n2 since it has a stop
if the current node is n2, I should get n21,n211,n212,n22 -- it should not
affected by the stop, since it only filter childnodes with stop attribute.
I get used to use for-each. Is there a way to do that with for-each?
Thanks!
> > I have xml tree like
> >
[quoted text clipped - 54 lines]
>
> ///Peter
Peter Flynn - 27 Sep 2006 22:08 GMT
> The XML has a type error. It just a fake data to demo what I want.
The problem is that if you want someone to work on what you provide,
it's a courtesy to provide data that can be used.
> It seems I didn't express clearly. What I need is from any node, I can get
> all names in its subtree, but exclude those with a stop attribute. check
[quoted text clipped - 21 lines]
> if the current node is n2, I should get n21,n211,n212,n22 -- it should not
> affected by the stop, since it only filter childnodes with stop attribute.
OK, now I get it.
> I get used to use for-each.
Don't. The for-each is normally kept for processing nodes out of
document sequence, or for processing nodes sorted into a different
order.
> Is there a way to do that with for-each?
Possibly, but that's procedural thinking. XSLT isn't like that.
This seems to do the trick:
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output method="text"/>
<xsl:strip-space elements="*"/>
<xsl:template match="field">
<xsl:value-of select="@name"/>
<xsl:text>: </xsl:text>
<xsl:apply-templates select="child::field[not(@stop='true')]"
mode="sub"/>
<xsl:text>
</xsl:text>
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="field" mode="sub">
<xsl:value-of select="@name"/>
<xsl:text> </xsl:text>
<xsl:apply-templates select="child::field[not(@stop='true')]"
mode="sub"/>
</xsl:template>
</xsl:stylesheet>
///Peter