[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message] Re: recursive template grabbing nested elements...
Hi Anthony, > i want to have a recursive template that finds the deepest <tab> > with state="on", and then grabs the preceding sibling and the > following siblings' (or parent's sibling) "id" attribute. Once you've found the deepest tab element, you can output whatever you want within a template for it, e.g.: <xsl:template match="tab"> current = <xsl:value-of select="@id" /> prev = <xsl:value-of select="preceding-sibling::tab/@id" /> next = <xsl:value-of select="following-sibling::tab/@id | ../following-sibling::tab [not(current()/following-sibling::tab)]/@id" /> </xsl:template> [Note that this doesn't get the parent's following You can work out the depth of an element by counting how many ancestors it has: count(ancestor::*) So finding the deepest tab element involves finding a calculated maximum and applying templates to the tab element that has that maximum. I would use a template like the following, which works through the tab elements by applying templates to them. If there's a following tab with a state of on that's more deeply nested, then the template moves on to that tab. Otherwise, it applies the template above to this tab element: <xsl:template match="tab" mode="deepest"> <xsl:variable name="depth" select="count(ancestor::*)" /> <xsl:variable name="next" select="following::tab[@state = 'on'] [count(ancestor::*) > $depth]" /> <xsl:choose> <xsl:when test="$next"> <xsl:apply-templates select="$next" mode="deepest" /> </xsl:when> <xsl:otherwise> <xsl:apply-templates select="." /> </xsl:otherwise> </xsl:choose> </xsl:template> You would call this template by applying templates to the first descendant tab element with a state of 'on', in 'deepest' mode: <xsl:apply-templates select=".//tab[@state = 'on'][1]" mode="deepest" /> Alternatively, you could use a more traditionally recursive template into which you pass all the tab elements that you might be interested in: <xsl:call-template name="deepest"> <xsl:with-param name="tabs" select=".//tab[@state = 'on']" /> </xsl:call-template> The template to handle this would keep track of the deepest tab found thus far and compare it to the first in the $tabs list. The new deepest tab is passed in to the next recursion of the template, if there are more tab elements left in the list to go through, or has templates applied to it if not. <xsl:template name="deepest"> <xsl:param name="tabs" /> <xsl:param name="deepest" select="/.." /> <xsl:variable name="new-deepest" select="count($tabs[1]/ancestor::*) > count($deepest/ancestor::*)" /> <xsl:choose> <xsl:when test="$tabs[2]"> <xsl:call-template name="deepest"> <xsl:with-param name="tabs" select="$tabs[position() > 1]" /> <xsl:with-param name="deepest" select="$tabs[1][$new-deepest] | $deepest[not($new-deepest)]" /> </xsl:call-template> </xsl:when> <xsl:when test="$new-deepest"> <xsl:apply-templates select="$tabs[1]" /> </xsl:when> <xsl:otherwise> <xsl:apply-templates select="$deepest" /> </xsl:otherwise> </xsl:choose> </xsl:template> I should think Dimitre will show you an alternative that is not as closely coupled with your source XML, using one of his generic templates. Cheers, Jeni --- Jeni Tennison http://www.jenitennison.com/ XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
|
PURCHASE STYLUS STUDIO ONLINE TODAY!Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced! Download The World's Best XML IDE!Accelerate XML development with our award-winning XML IDE - Download a free trial today! Subscribe in XML format
|