I am trying to get value-of $deal/total_price
. In the first block, I am able to get value and everything works great. In the second block where I am using value-of
to set the variable named deal
, I get an error when trying to display $deal/total_price
. How can I return $deal/total_price
using setup in second block?
Works:
<xsl:variable name="deal" select="/webpage/results/cars/*[partner_name = $company_name and vehicle_class_description = $vehicle_class_description_full]" />
<xsl:value-of select="$deal/total_price"/>
Does Not Work :
<xsl:variable name="deal">
<xsl:value-of select="/webpage/results/cars/*[partner_name = $company_name and vehicle_class_description = $vehicle_class_description_full]"/>
</xsl:variable>
<xsl:value-of select="$deal/total_price"/>
I am receiving the following errors/warnings:
Warning: XSLTProcessor::transformToXml(): Invalid type
Warning: XSLTProcessor::transformToXml(): runtime error:
Warning: XSLTProcessor::transformToXml(): XPath evaluation returned no result
With <xsl:variable name="deal" select="/webpage/results/cars/*[partner_name = $company_name and vehicle_class_description = $vehicle_class_description_full]" />
the variable type is defined by evaluating the select
XPath expression which returns a node-set in XSLT/XPath 1.0. You can then do XPath navigation on the node-set, such as selecting child nodes.
With
<xsl:variable name="deal">
<xsl:value-of select="/webpage/results/cars/*[partner_name = $company_name and vehicle_class_description = $vehicle_class_description_full]"/>
</xsl:variable>
the variable type is a result tree fragment containing a text node with the string value of the first node selected by the inner value-of
. With a variable of type result tree fragment you can't do any XPath navigation, you can output its string value using value-of
or its tree fragment using copy-of
. If you want to do XPath navigation then you first need to use exsl:node-set
or similar to convert the result tree fragment into a node-set, but even if you do that for your second sample you would get with exsl:node-set($deal)
a node-set with a document node containing a text node. Thus if you want to have a variable containing nodes in XSLT 1.0 you need to use
<xsl:variable name="deal-rtf">
<foo>
<bar>...</bar>
</foo>
</xsl:variable>
<xsl:variable name="deal" select="exsl:node-set($deal-rtf)" xmlns:exsl="http://exslt.org/common"/>
<xsl:value-of select="$deal/foo/bar"/>
Some XSLT 1.0 processors (notably the various MSXML versions as used by IE or Edge and XslTransform
in the .NET framework) do not support exsl:node-set
but rather a similar function in a proprietary namespace (i.e. <xsl:variable name="deal" select="ms:node-set($deal-rtf)" xmlns:ms="urn:schemas-microsoft-com:xslt"/>
).
Inside of an xsl:variable
you can of course use xsl:choose
, e.g.
<xsl:variable name="deal-rtf">
<xsl:choose>
<xsl:when test="...">
<xsl:copy-of select="/webpage/results/cars/*[partner_name = $company_name and vehicle_class_description = $vehicle_class_description_full and pay_now = 'Y']"/>
</xsl:when>
<xsl:otherwise>
<xsl:copy-of select="webpage/results/cars/*[partner_name = $company_name and vehicle_class_description = $vehicle_class_description_full]"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="deal" select="exsl:node-set($deal-rtf)" xmlns:exsl="http://exslt.org/common"/>
<xsl:value-of select="$deal/total_price"/>
The problem is that the second version returns a RTF(Resulting Tree Fragment) and not a node-set like the first version. An XPath query cannot be applied to a RTF, it can only be applied to a node-set.
An explanation of the difference can be found here at Oracle.
In XSLT-1.0 you cannot avoid that, like it is explained here at StackOverflow.
I quote from the Oracle link:
A result tree fragment is equivalent to a node-set that contains just the root node.
You cannot apply operators like "/", "//" or predicate on a result tree fragments. They are only applicable for node-set datatypes.
The (probably easiest) solution would be using XSLT-2.0, because in XSLT-2.0 all variables are node-sets and RTFs have been extinguished.