Re: [xsl] regarding xpath

Subject: Re: [xsl] regarding xpath
From: Matt Gushee <mgushee@xxxxxxxxxxxxx>
Date: Wed, 24 Apr 2002 04:37:01 -0600
On Wed, Apr 24, 2002 at 09:40:22AM -0000, william locksman wrote:
> 
> <colleges>
> 
> <college id = "1">
> <name>A College</name>
> </college>
> 
> <college id = "2">
> <name>B College</name>
> </college>
> 
> <college id = "1">
> <name>C College</name>
> </college>
> 
> </colleges>
> 
> to print the college names,
> if i write an XPATH expression like
> -----------------------------------------------
> <xsl:for-each select="/colleges/college/name">
> <xsl:value-of select="."/>.
> </xsl:for-each>
> -----------------------------------------------
> OR
> -----------------------------------------------
> <xsl:for-each select="//colleges/college/name">
> <xsl:value-of select="."/>.
> </xsl:for-each>
> -----------------------------------------------
> OR
> -----------------------------------------------
> <xsl:for-each select="//college/name">
> <xsl:value-of select="."/>.
> </xsl:for-each>
> -----------------------------------------------
> 
> for all the above XPATH expressions in select , i seem to be 
> getting the names. If so then what is the significant difference 
> between the three statements??

Given the input shown in your example, there shouldn't be any difference
in the results. However:

 * If your input document had a different structure, you might see different
   results from the different expressions. For example, if the structure were

     <colleges>
       <region>
         <college>
         ...

   then the first expression would return nothing, while the second and third
   would return the same results as in your example. And so on ...

 * For performance reasons, it's better to avoid using '//'. Your second and
   third expressions will cause the processor to search the entire document 
   tree* looking for elements named 'colleges' or 'college', respectively.

   If you must use '//', try to use it as far down the tree as possible. That
   is, if you want to process all <college> elements, and you know the root
   element is <college>, but you don't know whether the <college> elements are
   direct children of <college> or not, then

     //college/name

   will work, but

     /colleges//college/name

   is preferable.

   Personally, I wouldn't use <xsl:for-each> in that situation. I would do
   something like this:

     <!-- Actually, this template is superfluous, since it simply duplicates
          the built-in behavior. It's just here for clarity. -->
     <xsl:template match="colleges">
       <xsl:apply-templates/>
     </xsl:template>   

     <xsl:template match="college/name">
       <xsl:value-of select="."/>
     </xsl:template>

   There are two reasons. One, it's more elegant. Two, it is my understanding
   that most or all XSLT processors are optimized for the apply-templates
   approach. Even if it doesn't help performance, it is unlikely to hurt.

* It's conceivable that as an optimization, an XSLT processor could look for only
  those 'colleges' (or 'college') elements that have the required descendants (or
  that have any descendants), but I doubt anyone actually does that, since it
  might be an improvement for this type of situation, but would introduce extra
  overhead everywhere else. 

Hope this helps.
-- 
Matt Gushee
Englewood, Colorado, USA
mgushee@xxxxxxxxxxxxx
http://www.havenrock.com/

 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


Current Thread