我对xslt完全不熟悉,所以如果这是一个愚蠢的问题,请原谅。 我需要声明一个变量并将其指向xml中2个可能的节点之一,具体取决于它们实际存在的位置。我正在尝试以下方法:
<xsl:variable name="DealNode">
<xsl:choose>
<xsl:when test="/AllResponse/Deals/Deal"><xsl:copy-of select="/AllResponse/Deals/Deal"/></xsl:when>
<xsl:otherwise><xsl:copy-of select="/AllResponse/BookDeals/BookDeal"/></xsl:otherwise>
</xsl:choose>
</xsl:variable>
这似乎有效,因为DealNode确实看起来像我期望的那样。但是,如果我现在这样做:
<xsl:variable name="TradeNode" select="$DealNode/Trades/Trade"/>
TradeNode仍为空。我做错了什么?
示例xml:
<AllResponse>
<Deals>
<Deal>
<Trades>
<Trade>
</Trade>
</Trades>
</Deal>
</Deals>
</AllResponse>
答案 0 :(得分:3)
目前接受的答案存在严重问题。如果根据以下XML文档评估其XPath表达式:
<AllResponse>
<BookDeals>
<BookDeal>
<Trades>
<Trade>
</Trade>
</Trades>
</BookDeal>
</BookDeals>
<Deals>
<Deal>
<Trades>
<Trade>
</Trade>
</Trades>
</Deal>
</Deals>
</AllResponse>
然后,与答案中的声明相反,提供的XPath表达式:
(/AllResponse/Deals/Deal | /AllResponse/BookDeals/BookDeal)[1]
不会选择联合的第一个参数,而是完全相反的(第二个参数)。
这样做的原因是union操作的结果总是按其节点的文档顺序排序 - 换句话说,节点集是一个集而不是一个序列。
这是一个正确的解决方案:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<xsl:variable name="vDealNode" select=
"/*/Deals/Deal | /*[not(Deals/Deal)]/BookDeals/BookDeal"/>
<xsl:copy-of select="$vDealNode"/>
</xsl:template>
</xsl:stylesheet>
当对上述XML文档应用此转换时,将选择所需的正确结果(作为union运算符的第一个参数的节点),并输出此选择的结果:
<Deal>
<Trades>
<Trade/>
</Trades>
</Deal>
解释:当条件$ns1
为$cond
并选择true()
时,我们要选择$ns2
时使用的正确通用表达式如果$cond
为false,则为:
$ns1[$cond] | $ns2[not($cond)]
在我们的具体案例中:
$ns1
是/*/Deals/Deal
,
$ns2
是/*/BookDeals/BookDeal
和
$cond
是boolean(/*/Deals/Deal)
在上面的一般表达中替换这些,并缩短:
/*/Deals/Deal[/*/Deals/Deal]
为:
/*/Deals/Deal
我们到达了此答案中使用的表达:
/*/Deals/Deal | /*[not(Deals/Deal)]/BookDeals/BookDeal
答案 1 :(得分:2)
定义变量的一种方法如下:
<xsl:variable name="DealNode" select="(/AllResponse/Deals/Deal | /AllResponse/BookDeals/BookDeal)[1]"/>
它构成了两个选定节点集的并集,并获取该并集中的第一个节点,以便在第一个表达式选择节点的节点时,如果第一个表达式没有选择任何内容,则选择第一个节点第二个表达式。
答案 2 :(得分:0)
XSLT1不完全支持结果树片段。要执行您尝试的操作需要exsl:node-set()
。
此外,即使在XSLT2中,正确的XPath也是$DealNode/Deal/Trades/Trade