根据测试,使用将Node分配给xsl:variable



我对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>

解释:当条件$condtrue()时,我们要选择$ns1,而当$cond为false时,我们想要选择$ns2时,要使用的正确通用表达式是:

$ns1[$cond] | $ns2[not($cond)]

在我们的具体案例中:

$ns1/*/Deals/Deal

$ns2/*/BookDeals/BookDeal

$condboolean(/*/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

相关内容

  • 没有找到相关文章

最新更新