Hi Everyone,
With an input XML of:
<xml>
<a>
<b>
<node id="1"/>
<node id="2"/>
<node id="3"/>
<c>
<node id="4"/>
<node id="5"/>
<node id="6"/>
<d>
<node id="7"/>
<node id="8"/>
<node id="9"/>
</d>
<e>
<node id="10"/>
<node id="11"/>
<node id="12" current="true"/>
</e>
</c>
</b>
<b>
<node id="13"/>
</b>
<b>
<node id="14"/>
</b>
<b>
<node id="15"/>
</b>
</a>
</xml>
I'm trying to identify those node elements immediately preceding and
following the one marked current="true", but ONLY if within the same <b>
element. For example, if node 6 is marked current, 5 and 7 will be
preceding and following, respectively. If node 12 is current (as shown), 11
will be preceding, and since there are no more node elements within that
<b>, there will be no following.
Note that the depth of any given node element may be considered arbitrary
within the heirarchy; the exact structure will not be known. I also need to
output something if there is no "preceding" or "following" node. There will
be only one node with the current="true" attribute.
I have come up with 2 approaches so far (following only shown as the same
approach can be used with preceding as well):
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output encoding="ascii" omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:variable name="current-node" select="//node[@current]"/>
<xsl:template match="/">
current: <xsl:value-of select="$current-node/@id"/><br/>
<xsl:choose>
<xsl:when
test="$current-node/following::node[1]/ancestor-or-self::b//node[@current]">
following: <xsl:value-of
select="$current-node/following::node[1]/@id"/><br/>
</xsl:when>
<xsl:otherwise>
no more<br/>
</xsl:otherwise>
</xsl:choose>
<xsl:choose>
<xsl:when test="generate-id($current-node/ancestor-or-self::b) =
generate-id($current-node/following::node[1]/ancestor-or-self::b)">
following: <xsl:value-of
select="$current-node/following::node[1]/@id"/><br/>
</xsl:when>
<xsl:otherwise>
no more<br/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
The first approach tests whether the "following" node's <b> ancestor
contains a node with the current="true" attribute.
The second approach tests if the <b> elements which are ancestors of the
current and following nodes are identical via the generate-id() function.
Can anyone comment on the relative merits / problems of either approach?
The first approach uses the frowned-upon //. Can anyone see a way to use a
clever predicate instead of the ancestor-or-self axis? Is there an obvious
solution that I'm missing?
Many thanks for your time,
Mike
_________________________________________________________________
Get your FREE download of MSN Explorer at http://explorer.msn.com/intl.asp.
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list