XSLT 2.0 and XPath 2.0 Programmer's Reference, 4th Edition (143 page)

BOOK: XSLT 2.0 and XPath 2.0 Programmer's Reference, 4th Edition
10.15Mb size Format: txt, pdf, ePub

sum(for $i in //item return $i/price * $i/quantity)

or more simply:

sum(//item/(price * quantity))

When things get difficult, it is possible to use functions such as
tokenize()
or
distinct-values()
to define the sequence that needs to be processed, and to use instructions such as

and

to do the processing. In XSLT 1.0 it was often necessary to write recursive templates to perform such calculations.

Recursion is still needed in XSLT 2.0 to handle more complex algorithms, particularly those that navigate a hierarchy or a graph, but it will often be done more conveniently using XPath function calls and stylesheet functions written using

rather than using

. Nevertheless, recursive use of

still has a role to play, so I will present a couple of examples.

The typical logic used to process a sequence using recursion is illustrated by the following pseudocode:

function process-sequence(sequence L) {

  if (not-empty(L)) {

     process(first(L));

     process-sequence(remainder(L));

  } 

}

That is, the function does nothing if the sequence is empty; otherwise, it processes the first item in the sequence and then calls itself to process the sequence containing all items except the first. The net effect is that each item in the sequence will be processed and the function will then exit. This particular approach to writing recursive algorithms is often known as
head-tail recursion
.

There are two main kinds of sequence that this logic is applied to: sequences of nodes, and strings containing separator characters. I will show one example of each kind; more complex examples can be found in Chapters 17 and 20.

Example: Using Recursion to Process a Sequence of Nodes

Here's an example for processing a sequence of nodes. XPath 2.0 provides
min()
and
max()
functions for finding the minimum and maximum of a set of atomic values, but it doesn't provide a way of processing a set of nodes and returning the one whose value for some expression is least or greatest. This can be done by computing the value of the expression for each of the nodes, passing these values into the
min()
or
max()
function and then searching the nodes to see which of them had this value, but this approach is rather inefficient because it involves visiting each node and calculating the expression twice. So we'll do it ourselves, using a recursive scan of the nodes, in a single pass. The specific task we will tackle is to look for the longest speech in a scene of a play.

Conceptually it's trivial: the maximum value of a set of numbers is either the first number or the maximum of the set of the numbers after the first, whichever is larger. We use XPath predicates for manipulating the node sequences: in particular,
[1]
to find the first node in the sequence, and
[position()! = 1]
to find the remainder.

Source

The source file
scene.xml
is the scene of a play. It starts like this:


SCENE I. Venice. A street.

Enter RODERIGO and IAGO


RODERIGO

Tush! never tell me; I take it much unkindly

That thou, Iago, who hast had my purse

As if the strings were thine, shouldst know of this.



IAGO

‘Sblood, but you will not hear me:

If ever I did dream of such a matter, Abhor me.


etc.


Stylesheet

The stylesheet
longest-speech.xsl
is shown below. It starts by defining a named template
max
. This template takes a node sequence called
list
as its parameter.

The first thing it does is to test whether this node sequence is nonempty (

). If it isn't, it gets the number of

element children of the first node in the list into a variable
$first
. Then the template calls itself recursively, passing all nodes except the first as the parameter, to determine the maximum value for the rest of the list. It then returns either the first value or the maximum for the rest of the list, whichever is greater. Finally, if the supplied list was empty, it returns zero.

The template rule for the root node of the source document simply calls the
longest-speech
template, passing the list of all

elements as a parameter.

Other books

The Austin Job by David Mark Brown
Army of the Wolf by Peter Darman
Hercules: A Matter of Trust by Heather Brooks
The Border Hostage by Virginia Henley
Write On! by Nancy Krulik
An Alien Rescue by Gordon Mackay
Walk Through Darkness by David Anthony Durham
Pain by Keith Wailoo