Subject: Re: [xsl] Re: getting all nodes from a certain level in the xml hierarchy From: Jeni Tennison <jeni@xxxxxxxxxxxxxxxx> Date: Fri, 27 Sep 2002 12:46:52 +0100 |
Hi Andrew, > Here Demitre uses the function count(ancestor::*|.) three times > within the same template - can anyone tell me if this gets > re-evaluated each time, therefore using a variable would be better, > or if it gets stored (as some kind of optimisation maybe), so using > a variable is unecessary? It will most probably get re-evaluated each time, unless the processor is very very smart. ancestor::* isn't likely to give you a *huge* node set (unlike descendant::*, for example), so this probably isn't a problem, but if it is, you could use a variable as follows: <xsl:key name="kDepth" match="Folder" use="count(ancestor::*)" /> <xsl:template match="/"> <xsl:for-each select="//Folder"> <xsl:variable name="depth" select="count(ancestor::*)" /> <xsl:if test="generate-id() = generate-id(key('kDepth', $depth)[1])"> <xsl:value-of select="concat('Level ', $depth, ': ')" /> <xsl:for-each select="key('kDepth', $depth)"> <xsl:value-of select="concat(@NAME, '; ')" /> </xsl:for-each> </xsl:if> </xsl:for-each> </xsl:template> There are two potential issues with this method that arise because you're for-eaching over *all* the Folder elements. One is that it might prove less efficient than only for-eaching over the *unique* Folder elements -- for-eaching might be less efficient than using a predicate to do the filtering. The second is that if you wanted to use position() anywhere within the outer xsl:for-each, you'd get the "wrong" value, because the position would be based on the location of the Folder amongst *all* the Folders rather than amongst the unique ones. A compromise, if either of those is a problem, would be to use: <xsl:key name="kDepth" match="Folder" use="count(ancestor::*)" /> <xsl:template match="/"> <xsl:for-each select="//Folder[generate-id() = generate-id(key('kDepth', count(ancestor::*))[1])"> <xsl:variable name="depth" select="count(ancestor::*)" /> <xsl:value-of select="concat('Level ', $depth, ': ')" /> <xsl:for-each select="key('kDepth', $depth)"> <xsl:value-of select="concat(@NAME, '; ')" /> </xsl:for-each> </xsl:if> </xsl:for-each> </xsl:template> where the calculation gets carried out twice per Folder element, rather than three times or once. I should point out, though, that I gather that some processors (Saxon, I think, but there might be others) attempt to save memory by only actually storing the value of a variable if it's used more than twice, so using a variable might make no difference whatsoever (aside from arguably making the code easier to read). As with all performance questions, the best advice is "try it and see". Cheers, 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] Re: getting all nodes fro, Andrew Welch | Thread | [xsl] problems with nested template, Christian Timmerer ( |
Re: [xsl] amp, Noel Golding | Date | AW: [xsl] Re: getting all nodes fro, Peter Menzel |
Month |