I'm trying to use a user-defined function in XSLT that repeatedly calls the value of a certain string. That string is based on the outcome of an XPath expression that doesn't change within the span of a single function call. I thought it would be a good idea to assign it to a variable rather than look it up over and over again.
Unfortunately, at least in Saxon's implementation, you cannot use an XPath expression requiring a node inside a function, even one based on an absolute path, without first using a throw-away line to let the function know you are discussing the root document rather than some other one.
So, for example, the following code throws an error:
<xsl:function name="udf:LeafMatch">
<xsl:param name="sID"></xsl:param>
<xsl:variable name="myLeaf" select="/potato/stem[@sessionID=$sID][scc]/scc/@leafnumber"/>
Normally, the solution is just to first call any global variable to give context. For example, the following works inside of an udf ($root is a variable identified with the root node):
<xsl:for-each select="$root">
<xsl:value-of select="/potato/stem[@sessionID=$sID][scc]/scc/@leafnumber"/>
</xsl:for-each>
But this doesn't work when trying to use Xpath to fix the value of a variable because I'm not allowed to put the expression within a for-each.
I also tried using
<xsl:choose><xsl:when select"$root"><xsl:value-of select="/potato/stem[@sessionID=$sID][scc]/scc/@leafnumber"/></xsl:when></xsl:choose>
to give it context, going on what I saw here:http://www.stylusstudio.com/xsllist/200504/post00240.html
That didn't work either.
FWIW, passing the variable into the function is problematic because the Xpath expression used to define "myleaf" depends on the context node, and I don't know how to get Xpath to call one path based on values in the current context node.
For example, in the code calling this function I have something like:
<xsl:for-each select="/potato/stem[eye]">
<leaf = "{udf:LeafMatch(@sessionID)}"/>
</xsl:for-each>
I'm working in the context of a /potato/stem[eye] node and using the udf to look for a /potato/stem[scc] node that has the same value of @sessionID. I don't know how to reference the value of @sessionID from the current context node in the predicate of an XPath searching for other nodes in a completely different part of the XML tree, so I was using a udf to do that. It was working fine until I decided to try to use a variable for the string rather than having the processor look it up each time.
I was trying to avoid going one level deeper (having my function itself call a named template or putting a named template inside my original for-each and having that named template call a function).
So my questions are:
A. For a user-defined function, how do I set a variable that depends on an XPath expression?
B. Is there a snazzy way in Xpath to use values drawn from the current content node in the predicates of the Xpath expression you are trying to test?
Both questions are quite unclear.
A: I assume you actually mean:
The answer: You can't. By definition there is no context node within an
xsl:function
. This is defined by the W3C XSLT 2.0 specification in the following way:You can, however, pass as a parameter the intended context node (or just the document node that must be used as current). Or, alternatively, you may refer to a globally defined variable.
B: This question is completely not understandable:
What is "snazzy"?
What is "current content node"? Please, provide an example of a specific task to be accomplished in the wanted "snazzy" way.