我对xslt完全不熟悉,所以如果这是一个愚蠢的问题,请原谅。我需要声明一个变量,并将其指向xml中两个可能的节点中的一个,这取决于它们中实际存在的节点。我正在尝试以下操作:
<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>
当前接受的答案存在严重问题。如果根据以下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]
不选择并集的第一个参数,但恰恰相反(第二个参数)。
原因是并集运算的结果总是按照其节点的文档顺序排序——换句话说,节点集是一个集合,而不是序列。
这里有一个正确的解决方案:
<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文档时,将选择所需的正确结果(作为并集运算符的第一个参数的节点),并输出此选择的结果:
<Deal>
<Trades>
<Trade/>
</Trades>
</Deal>
解释:当条件$cond
为true()
时,我们要选择$ns1
,而当$cond
为false时,我们想要选择$ns2
时,要使用的正确通用表达式是:
$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
定义变量的一种方法如下:
<xsl:variable name="DealNode" select="(/AllResponse/Deals/Deal | /AllResponse/BookDeals/BookDeal)[1]"/>
它形成了两个选定节点集的并集,并取并集中的第一个节点,这样,如果第一个表达式选择了一个节点,则取该节点,如果第一表达式没有选择任何内容,则取第二个表达式选择的第一个节点。
XSLT1不完全支持结果树片段。要做您正在尝试的事情,需要exsl:node-set()
。
此外,即使在XSLT2中,正确的XPath也是$DealNode/Deal/Trades/Trade