[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message]

Re: Re: getting all nodes from a certain level in the

Subject: Re: 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
xsl for each all nodes
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

PURCHASE STYLUS STUDIO ONLINE TODAY!

Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced!

Buy Stylus Studio Now

Download The World's Best XML IDE!

Accelerate XML development with our award-winning XML IDE - Download a free trial today!

Don't miss another message! Subscribe to this list today.
Email
First Name
Last Name
Company
Subscribe in XML format
RSS 2.0
Atom 0.3
Site Map | Privacy Policy | Terms of Use | Trademarks
Free Stylus Studio XML Training:
W3C Member
Stylus Studio® and DataDirect XQuery ™are products from DataDirect Technologies, is a registered trademark of Progress Software Corporation, in the U.S. and other countries. © 2004-2013 All Rights Reserved.