Subject: Re: [xsl] Selecting a subset of siblings using following-sibling From: Jeni Tennison <jeni@xxxxxxxxxxxxxxxx> Date: Fri, 23 Nov 2001 19:10:26 +0000 |
Hi Liat, > I need to extract the nodes B through D. I have tried to do this using: > > <xsl:for-each select="child::B/following-sibling::*[(name(.) != 'E')]"> > do something here... > </xsl:for-each> That path selects the following siblings of the B element whose name is not 'E' - everything after the B element that isn't an E element in other words. > but I seem to be getting the nodes B, C, D, F and G (which is not > desirable, since I only need nodes B, C and D). I'm not sure if this > is the right (read elegant) approach, but I can't figure out another > way to select a subset of nodes and define its boundaries (i.e., is > it possible to define the boundaries as 'upper' and 'lower' limits > with node B being the 'lower' limit and node D the 'upper' limit?). There are a few ways of approaching this. The obvious one is to select the B, C and D elements explicitly with: <xsl:for-each select="B | C | D"> ... </xsl:for-each> But I assume that you can't do that for some reason. Another approach is to select all the child nodes of the current DETAIL element that (a) have a B element as a preceding sibling, or are themselves a B element and (b) have a D element as a following sibling, or are themselves a D element. You can do this with: <xsl:for-each select="*[(preceding-sibling::B or self::B) and (following-sibling::D or self::D)]"> ... </xsl:for-each> Another method is to use templates rather than xsl:for-each and step through the elements one by one. To start off, apply templates just to the B element: <xsl:apply-templates select="B" /> Now have a template that matches all children of the DETAIL element and does whatever you want it to do (the stuff inside the xsl:for-each): <xsl:template match="DETAIL/*"> ... </xsl:template> Once you've done whatever it is for that element, then you need to see whether you need to apply templates to the next element. Basically you apply templates to the next element as long as this element isn't the D element (which is where you want the journey to stop): <xsl:template match="DETAIL/*"> ... <xsl:if test="not(self::D)"> <xsl:apply-template select="following-sibling::*[1]" /> </xsl:if> </xsl:template> Using the template will probably be more efficient because it will only visit the nodes that you're interested in, compared to the path above which will visit *all* the children of the DETAIL element while trying to work out whether it should process them or not. I hope that helps, Jeni --- Jeni Tennison http://www.jenitennison.com/ XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: [xsl] Selecting a subset of sib, cutlass | Thread | [xsl] positional predicates in XPat, Howard Katz |
Re: [xsl] grouping within for-each , Jeni Tennison | Date | [xsl] positional predicates in XPat, Howard Katz |
Month |