[xsl] Predicates vs. Axes

Subject: [xsl] Predicates vs. Axes
From: "Michael Peet" <mjpeet@xxxxxxxxxxx>
Date: Mon, 03 Jun 2002 15:22:18 -0400
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



Current Thread