Groups | Blog | Home
all groups > dotnet xml > september 2006 >

dotnet xml : Urgent XSL question, please help, thanks


davidw
9/26/2006 1:08:01 PM
I have xml tree like

<root>
<field name="l1">
<field name="l11">
<field name="l111"/>
<field name="l112"/>
</field>
<field name="l2" stop="true">
<field name="l21">
<field name="l211"/>
<field name="l212"/>
</field>
<field name="l22"/>
</field>
<field name="l3"/>
</root>

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

<xsl:for-each select=".//field[not(@stop)]/field">
<xsl:value-of select="@name"/>,
</xsl:for-each>

It do the recursive loop, the problem is if the current context is "l2", it
will not work. The idea is it check all childnodes without "stop", not the
start node (the current context). I have no way to know if the node is top
node in // , and I don't know how to get current level ( I remember there
isn't such function).

Any idea?

Thanks!

davidw
9/26/2006 9:40:28 PM
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!



[quoted text, click to view]

davidw
9/26/2006 9:40:48 PM
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!



[quoted text, click to view]

Peter Flynn
9/26/2006 10:20:09 PM
[quoted text, click to view]

Your XML is not well-formed: it's missing a </field> end-tag before the
</root> end-tag.

[quoted text, click to view]

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>&#xA;</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
--
XML FAQ: http://xml.silmaril.ie/


Peter Flynn
9/27/2006 10:08:36 PM
[quoted text, click to view]

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.

[quoted text, click to view]

OK, now I get it.

[quoted text, click to view]

Don't. The for-each is normally kept for processing nodes out of
document sequence, or for processing nodes sorted into a different
order.

[quoted text, click to view]

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>&#xA;</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>

AddThis Social Bookmark Button