我正在尝试获取value-of $deal/total_price
。在第一块,我能够获得价值,一切都很好。在第二个块中,我使用value-of
设置名为deal
的变量,在尝试显示$deal/total_price
时出错。如何使用第二块中的设置返回$deal/total_price
?
作品:
<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"/>
不工作:
<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"/>
我收到以下错误/警告:
Warning: XSLTProcessor::transformToXml(): Invalid type
Warning: XSLTProcessor::transformToXml(): runtime error:
Warning: XSLTProcessor::transformToXml(): XPath evaluation returned no result
对于<xsl:variable name="deal" select="/webpage/results/cars/*[partner_name = $company_name and vehicle_class_description = $vehicle_class_description_full]" />
,变量类型是通过计算select
XPath表达式来定义的,该表达式返回XSLT/XPath 1.0中的节点集。然后可以对节点集进行XPath导航,例如选择子节点。
带
<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>
变量类型是包含具有由内部CCD_ 8选择的第一节点的字符串值的文本节点的结果树片段。对于结果树片段类型的变量,您不能进行任何XPath导航,可以使用value-of
输出其字符串值,或者使用copy-of
输出其树片段。如果要进行XPath导航,则首先需要使用exsl:node-set
或类似方法将结果树片段转换为节点集,但即使对第二个示例进行了转换,使用exsl:node-set($deal)
也会得到一个节点集,其中包含一个包含文本节点的文档节点。因此,如果您希望在XSLT1.0中有一个包含节点的变量,则需要使用
<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"/>
一些XSLT1.0处理器(尤其是.NET框架中IE或Edge和XslTransform
使用的各种MSXML版本)不支持exsl:node-set
,而是在专有名称空间(即<xsl:variable name="deal" select="ms:node-set($deal-rtf)" xmlns:ms="urn:schemas-microsoft-com:xslt"/>
)中支持类似的功能。
在xsl:variable
内部,您当然可以使用xsl:choose
,例如
<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"/>
问题是第二个版本返回的是RTF(Resulting Tree Fragment),而不是像第一个版本那样的节点集。XPath查询不能应用于RTF,只能应用于节点集。
有关差异的解释,请访问Oracle。
在XSLT-1.0中,您无法避免这种情况,就像StackOverflow中所解释的那样。
我引用Oracle链接:
结果树片段相当于只包含根节点的节点集
不能在结果树片段上应用诸如"/"、"//"或谓词之类的运算符。它们仅适用于节点集数据类型。
(可能最简单的)解决方案是使用XSLT-2.0,因为在XSLT-2.2中,所有变量都是节点集,RTF已经熄灭。
正如其他人所说,只有使用xsl:variable
标记中的内联select
属性才能生成可用的节点集。
但是,您不必使用更高版本的XSLT或特定的XSLT扩展,这在共享主机上可能是不可能的。
为了满足备用节点集的需要,诀窍是使用|
并集运算符来加入每个备用节点集,但要确保[ ]
中不需要的备用节点的条件不返回任何节点。
测试不必依赖于[ ]
所附加的元素,而是可以使用它所需要的任何变量和文字,以确保备选方案只生成具有自己唯一标准的节点集,而不会为其他节点集生成。
为了在上面的评论中用你的例子的变体来说明:
<xsl:value-of select="/webpage/results/cars/*[($access_type = 'web') and (partner_name = $company_name) and (vehicle_class_description = $vehicle_class_description_full) and (pay_now = 'Y')]|/webpage/results/cars/*[($access_type = 'phone') and (partner_name = $company_name) and (vehicle_class_description = $vehicle_class_description_full)]"/>
其中CCD_ 23是不是被测试的XML数据的直接部分的变量。
如果选择太多,它可能会变得笨拙,但可以通过测试每个备选方案来减轻这种情况,以确保它只在需要时生成一个节点集,否则为空。然后简单地将它们放在select
中,它们之间有一个|
。