RE: [xsl] Looping using XSL

Subject: RE: [xsl] Looping using XSL
From: "Passin, Tom" <tpassin@xxxxxxxxxxxx>
Date: Wed, 2 Oct 2002 11:41:50 -0400
[ Josh Campbell]

Vasu Chakkera wrote:
> > Doesnt <xsl:for-each select="//*[position() &lt;= rating]"> iterate 
> > through all the child elements of the context node ., in this case 
> > "mood".. so essentially since it has only one child 
> element( "rating" 
> > ), It should iterate only once irrespective of the condition 
> > *[position() &lt;= rating]">
> > so you xsl should produce only one line.
> > <div class="moodbar"><img 
> src="layout/global/pics/mood-red.gif" alt="" 
> > /></div>
> > Vasu
> That's what I've just found...though I appreciated the idea 
> :-) Sorry if the words 'looping' and 'iterate' have confused 
> the issue but 
> I'm not sure what else to call it.
> I guess what's needed is some way of testing against the 
> number in the 
> rating node and write out the html line until the rating is equalled.

No, that is an unhelpful way to look at things.  With this approach (the
one Wendell illustrated), the idea is to select a set of nodes and, for
each of them, output your img element.  It is a matter of selecting a
set, then operating on the set.  The cleverness is in figuring out how
to select the right set.  This is true for many of the xslt questions
that get asked.  Once you can select the right set of nodes, the problem
is practically solved.  

Remember, that is what xpath expressions do - they select (ordered) sets
of nodes.  So node sets are usually the basic material to work with.

In Wendell's version, the set gets defined in two places.  First with 

select="$plentynodes[position() &lt;= rating]"

Then this set is refined down to a smaller set in the xsl:for-each

To make this more clear, here is a variation that selects the set in one
place, in a single variable, and uses the nodes in the stylesheet rather
than in the source document (the stylesheet is likely to have more than
enough nodes even if the source document is too short - also you can add
more nodes to the stylesheet if you need to.  I have wrapped the "mood"
element in a "root" element to illustrate.

<xsl:stylesheet version="1.0"
   <xsl:output encoding='iso-8859-1' />

   <xsl:variable name='rating' select='/root/mood/rating' />
   <xsl:variable name='nodes' 
select='document("")//xsl:stylesheet/descendant-or-self::*[$rating >=
position()]' />

   <xsl:template match="/root">
         <xsl:for-each select='$nodes'>
            <your-image-element-here />

You could also use apply-templates instead of for-each, but then you
would have to write another little template, so this is a bit more

If you think that this still looks like an iteration, that is true but
does not reflect what actually goes on - conceptually, at least, since
we do not know how any random processor actually implements these
operations.  Conceptually, the processor takes all the nodes in the node
set, performs the specified operations on them ***separately and in any
order***, then ***assembles the results*** in document order or in any
specified sort order. (Mike and Jeni, if you would, please tune up this
description if it is off the mark).

At least one processor, XT, is said to actually operate "out of order"
this way.  Of course, a processor **could** implement these operations
by looping through the list of nodes, but conceptually that is not

This distinction - selecting sets of nodes and operating on their nodes
independently vs iterating through a fixed list - is crucial to
developing an effective xslt mindset.


Tom P

 XSL-List info and archive:

Current Thread