Read XSLT 2.0 and XPath 2.0 Programmer's Reference, 4th Edition Online
Authors: Michael Kay
It's still true that this is equivalent to a nested-loop expression:
for $c in doc(‘customers.xml’)//customer
return
for $p in doc(‘products.xml’)//product [$c/orders/product-code = $p/code]
return $c/line/cost
The other way to think about this, particularly if you are familiar with SQL, is as a relational join. The system isn't actually obliged to evaluate the
for
expression using nested loops (this applies whether you write it in the abbreviated form using multiple range variables separated with commas, or whether you use the expanded form shown above). Instead, the optimizer can use any of the mechanisms developed over the years in relational database technology to evaluate the join more rapidly. There's no guarantee that it will do so, so you need to use potentially expensive constructs like this with some care.
One of the differences between the open-source Saxon-B product and its commercial cousin Saxon-SA, is that Saxon-SA optimizes joins. Both products will try to move subexpressions out of a loop if they don't depend on the range variable. So the expression
doc(‘products.xml’)//product
will probably only be evaluated once, and the expression
$c/orders/product-code
will only be evaluated once for each customer. But after this, Saxon-B will compare every product code in the customer file with every product code in the product file, while Saxon-SA will create an index (in effect, doing a hash join). The bigger the data file, the more of a difference this makes.
In XSLT, you can “hand-optimize” a join by using keys: see the description of the
Example
Expression | Description |
count( for $i in 1 to 8, $j in 1 to 8 return f:square($i , $j)) | Assuming that f:square(row , column) returns an integer identifying the piece that occupies a square on a chessboard, or an empty sequence if the square is unoccupied, this expression returns all the pieces on the board. |
Simple Mapping Expressions
You may have noticed that there are some strong similarities between
for
expressions and path expressions. The expression:
for $c in chapter return $c/section
returns exactly the same result as the path expression:
chapter/section
However, there are some significant differences between
for
expressions and path expressions: