I had posted another question with this as one aspect of it. I was told to clarify the question, but that question was already pretty long and complicated, so I created a new one.
I want to know if there is standard way of referencing the current node's attribute in an XPath expression testing for another one.
For an example, consider the following XSLT
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<xsl:for-each select="potato/stem[eye]">
In session <xsl:value-of select="@sessionID"/>, the potato had <xsl:value-of select="/potato/stem[@sessionID=@sessionID][scc]/scc/@leafnumber"/> s.c.c. leaves.
</xsl:for-each>
</xsl:template>
(XML source at bottom of this question.) (Note that the for-each references nodes of type stem[eye] but the second value requested references nodes of type stem[scc], which are on a different branch of the source XML tree.)
Now, obviously, the "@sessionID=@sessoinID" part of that is mostly meaningless because XPath perceives this as "The value of the sessionID attribute of the node should equal ... the value of the sessionID attribute of the node."
But what I want to say is "Test to make sure the value of the seesionID attribute of that node (the one in the XPath expression) is the same as the sessionID of the node of whatever /stem[eye] node I'm in right now."
I can't do this with a variable, because you are not allowed to declare a variable within a for-each clause.
For reference, this is the XML source. Its structure is not what one would like, but it is what I have to work with.
<?xml version="1.0" encoding="utf-8"?>
<potato>
<stem sessionID="1">
<eye number = "25"/>
</stem>
<stem sessionID="3">
<eye number = "33"/>
</stem>
<stem sessionID="1">
<scc leafnumber = "234" />
</stem>
<stem sessionID="2">
<scc leafnumber = "433"/>
</stem>
<stem sessionID="3">
<scc leafnumber = "463"/>
</stem>
<stem sessionID="1">
<agd leafnumber = "154"/>
</stem>
<stem sessionID="2">
<agd leafnumber = "233"/>
</stem>
<stem sessionID="3">
<agd leafnumber = "113"/>
</stem>
</potato>
The output I'm looking for is:
In session 1, the potato had 234 s.c.c. leaves.
In session 3, the potato had 463 s.c.c. leaves.
(Of course, this is all just sandbox example. I realize there are probably easy ways to accomplish the above output in a completely different manner, but I hope this example gets across my question, which is how to use values associated with the current node (say, in a for-each) in a predicate for an XPath searching out a different one.)
The current node is the node in the source XML document best matched by an XSLT template. The current node becomes the starting context node for each XPath expression in the matched template. The current node can be accessed as current() within XPath predicates.
1. Well, more precisely, node() means child::node(), and @* means attribute::*, so it is matching all children and attributes of the context node. (It doesn't match document nodes or namespace nodes).
XSLT current() Function The current() function returns a node-set that contains only the current node. Usually the current node and the context node are the same.
In XSLT 1.0 you can use the standard function current()
which refers to the node that is matched by the current template or the inner-most xsl:for-each
:
/potato/stem[@sessionID=current()/@sessionID][scc]/scc/@leafnumber
or by defining a key (at a global level):
<xsl:key name="kPotById" match="stem[scc]" use="@sessionID"/>
and referencing this key:
key('kPotById', @sessionID)/scc/@leafnumber
In XSLT 2.0 / XPath 2.0 you have additional ways to express this (range variables):
for $thisSessionID in @sessionId
return
/potato/stem[@sessionID=$thisSessionID][scc]/scc/@leafnumber
Use e.g. current()/@sessionID
to access the sessionID
attribute of the currently processed node (e.g. the one processed by the for-each in your sample or by an apply-templates with push processing).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With