XSLT and XPath function reference in alphabetical order
(Excerpt from “XSLT 2.0 & XPath 2.0” by Frank Bongers, chapter 5, translated from German)
Context information within a sequence
The current() function returns a node sequence which consists of a single node, the Current Node.
Purpose of use:
The current node returned by the current() function is the currently processed node. In most cases, this corresponds to the context node being also accessible via the XPath patterns "." or "self::node()". Therefore, it is usually not necessary to distinguish between both, although in a strict sense they are two different concepts.
Difference between XSLT 1.0 and XSLT 2.0:
In XSLT 1.0, current() cannot be used in XPath patterns (for example in the match attribute of a template) because patterns shall be context-free per definition. Otherwise it would make a difference for the pattern comparison regarding which node is the current node at the time of the evaluation. This is not the case in XSLT 2.0: Now, the current() function can be used within XPath patterns and returns, in this context, the node currently tested during the pattern evaluation.
However, inside predicates of more complex XPath expressions, the context node changes during the predicate tests to the respective tested node. Whereas the current node as reference node remains unchanged. Therefore, the possibility to test in the course of the processing whether context node and current node are identical or share some characteristics may be important. The former in order to recognise whether a node is compared with itself, the latter in order to be able to make references between the current node and the context node.
The current() function which reliably returns the current node offers in such cases the possibility to test the context node against the current node.
The current() function is also used in nested instruction hierarchies. Here, for example, nested xsl:for-each commands may be possible, whereby the currently processed node of the outer loop constitutes the reference node for a pattern of the inner loop.
Example - »inner join« in XSLT with current( ):
If subqueries are used in XPath expressions – comparable to »inner joins« in SQL – the current() function can be used to make transcontextual comparisons, for example in a XML document similar to this:
<?xml version="1.0" encoding="ISO-8859-1"?> <favouriteSongs> <song> <title>The Last Time</title> <artist>Rolling Stones</artist> <artist> The Who </artist> </song> <song> <title>I wanna be your man</title> <artist>Beatles</artist> <artist>Rolling Stones</artist> </song> ... </favouriteSongs>
A song can be assigned to several artists, as the excerpt from the XML document shows. Here, a list of the songs together with all artists shall be outputted. In addition, after each artist the songs of the respective artist contained in the list shall be listed, but without repeating the currently outputted song.
Here, the template outputting the individual songs of the list:
<xsl:template match="song"> <h3><xsl:value-of select="title"/></h3> <!-- Output of the artists playing the song --> <p><b>Artists: </b><br/> <xsl:for-each select="artist"> <xsl:value-of select="."/> <!-- List of songs of the same artist --> (also: <xsl:for-each select="//song[artist/text()=current()/text()][. != current()/parent::song]"> <xsl:value-of select="title"/> <xsl:if test="position() != last()"> <xsl:text>, </xsl:text></xsl:if> </xsl:for-each> )<br/> </xsl:for-each> </p> </xsl:template>
A fragment of the result document could be as follows:
... <h3>Song: The Last Time</h3> <p><b>Artists: </b><br> Rolling Stones(also: I wanna be your man, Satisfaction)<br> The Who(also: My Generation) <br> </p> <h3> ...
The outer xsl:for-each loop outputs all artists of the song currently processed in the template:
The further songs to be listed in the context of the outputted artists are processed in an inner xsl:for-each loop:
<xsl:for-each select="//song[artist/text() = current()/text()][. != current()/parent::song]">
The relevant part is the XPath expression in the select attribute of the inner xsl:for-each loop. At first, all <song> elements of the document are selected and filtered with the help of two predicates.
Now, for each song is tested in document order with the first predicate
[artist/text() = current()/text()]
whether it has an <artist> element whose text node (the artist name) corresponds to the one of the current artist name. The current() current node is the currently outputted artist element of the outer xsl:for-each loop, whereas the artist elements which are compared (the context nodes) are the ones of the currently tested songs of the inner xsl:for-each loop.
Now, it is necessary to prevent that in the song list besides the artists also the title of the currently outputted songs (the current node of the template itself) is listed. This is achieved by a further filtering with the second predicate:
[. != current()/parent::song]
Here, the currently outputted current() artist element is the starting point and on its parent axis the way leads back to the <song> element which has previously been outputted in the main list. This <song> element must not be identical with the song currently tested for the context list. In the case of different nodes, the tested song is outputted.
current() => node set
current() as item()
Possible compatibility problems with XSLT 2.0 to XSLT 1.0:
The most important new feature is that current() can now be used in XSLT 2.0 within XPath patterns. In this case, the expression stands for the node currently tested in the framework of the pattern evaluation. Therefore, the part of the stylesheet in which the pattern is located should not be processed in the downward compatible mode. Under XSLT 2.0, the return value is not defined as a node set (consisting of one node, the current node) but generalised to »item«. This should not cause any troubles.
|<< back||next >>|
Copyright © Galileo Press, Bonn 2008
Printing of the online version is permitted exclusively for private use. Otherwise this chapter from the book "XSLT 2.0 & XPath 2.0" is subject to the same provisions as those applicable for the hardcover edition: The work including all its components is protected by copyright. All rights reserved, including reproduction, translation, microfilming as well as storage and processing in electronic systems.
Galileo Press, Rheinwerkallee 4, 53227 Bonn, Germany