XSLT is a declarative language that doesn't allow updating variables.
Hence there are no constructs to create iterative loops, which are
well-known from imperative programming languages like C(++) or Java.
(Even <xsl:for-each> isn't really a loop construct.)
To solve iterative problems you have to transform them into recursive
problems - no problem if you're familiar with that.
In XSLT this means defining a named template and calling it with appropriate parameters. The resulting code could become slightly unreadable.
Don't bother - here comes the loop compiler!
The XSLT Loop Compiler allows you thinking iterative. It performs the necessary transformation into recursive template calls. The loop language introduces five new elements. They could be considered as XSLT extension elements. However, the resulting code is fully XSLT conformant - it doesn't use any proprietary extension elements or functions. The code should run with every compliant XSLT processor.
Before we're diving into the details: how to use this compiler?
An example is on my main XSLT page at the end of the loop compiler section.
All loop elements belong to the namespace
"http://informatik.hu-berlin.de/loop".
The prefix I chose was loop.
There's no "www" contained in the namespace - it isn't an URL for retrieving something.
<loop:for>
performs a traditional for-loop, i.e. start and end values are known, the loop repeats by increasing (or decreasing) a counter by a fixed step.
The step attribute is optional.
If it is omitted, step defaults to 1.
If step < 1 then the loop runs until
$qname < to, otherwise until
$qname > to.
Example:
gives an upside down multiplication table up to ten.
<loop:while>
performs a traditional while-loop, repeating while a test expression evaluates to true.
A <loop:while> may have in this order zero or more
<xsl:variable> children, one optional
<loop:do> child element, one optional
<loop:last> child element, and one or more
<loop:update> children (see below).
Actions to be performed every turn of the loop must be placed inside of
<loop:do>, actions to be performed when the loop
terminates must be placed inside of <loop:last>.
The element <loop:last> was introduced because all
variables will have their old values after returning from the loop.
Therefore one would have no means to access the final values of these
variables.
Sometimes one needs the same computed value inside of
<loop:do>, <loop:last>,
<loop:update>, or even as part of the test
expression of <loop:while>.
This can be simplified by storing the computed value as a
<xsl:variable>.
These variables must appear first as children of
<loop:while>. Hence the execution of a while loop
is: first compute all variables, next evaluate the test expression, if
true then perform all actions inside of
<loop:do>, update the variables and repeat,
otherwise perform all actions inside of <loop:last>
and terminate (i.e. return from the loop). This kind of loop is a
"tail recursion".
Note: Though a variable is declared only inside of
<loop:while> it may be referenced already within
the test expression of <loop:while>'s start tag.
An example showing <loop:while> follows below,
after introducing <loop:update>.
<loop:update>
allows assigning a variable a new value for the next turn.
A
<loop:update> element is translated into an XSLT
<xsl:with-param> element, therefore it has to follow
the same rules.
|
respectively |
Every variable to be upated must be declared beforehand, i.e.
qname must refer to a variable or parameter that is
visible at the parent loop element.
If a <loop:while> contains no
<loop:update> at all, the loop will repeat infinitely
(which is most probably not what you want).
While
<loop:update> usually will be used within a
<loop:while> loop, it can of course also be
placed inside of <loop:for> to alter additional
variables. However, the counter of <loop:for> (its
name attribute) can't be changed this way.
Example:
This loop computes the square root of a given number
(input).
A complete stylesheet containing both examples of this page can be
downloaded here.
Well, these are not the kind of problems XSLT was
designed for. More reasonable examples, demonstrating
<loop:while> and <loop:update>,
can be found on my XSLT page,
particularly tokenizer.lxsl,
number-total.lxsl and
total-sales.lxsl.
|