2012-03-30 24 views
1

我完全不熟悉xslt,所以請原諒我,如果這是一個愚蠢的問題。 我需要聲明一個變量,並將它指向xml中2個可能的節點之一,具體取決於它們實際上存在哪個節點。我想以下幾點:使用取決於測試的指定節點到xsl:變量

<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

你在使用XSLT 1還是2? – 2012-03-30 17:15:26

+0

對不起,應該說它的xslt 1 .. – StevieG 2012-03-30 17:17:06

+0

@StevieG:注意到目前接受的答案是相當有問題的可能是有用的。欲瞭解更多信息,請閱讀我的答案。 – 2012-03-31 04:14:56

回答

2

一種方法以定義變量如下:

<xsl:variable name="DealNode" select="(/AllResponse/Deals/Deal | /AllResponse/BookDeals/BookDeal)[1]"/> 

形成所選的兩個節點集的聯合與採取第一如果第一個表達式選擇了一個節點,那麼如果第一個表達式沒有選擇任何內容,那麼第二個表達式將選擇第一個節點。

+0

工程款待,非常感謝! – StevieG 2012-03-30 17:40:12

+0

不好意思,但是這可以在一個序列上工作 - 兩個*節點集合*是一個新的節點集合,其中節點(按定義)是按照文檔順序。因此,在一般情況下'($ ns1 | $ ns2)[1]'不會選擇'$ ns1'的第一個節點 - 而是選擇兩個節點集合的第一個節點(按文檔順序) - 這可能是屬於'$ ns'的節點或屬於'$ ns2'的節點。請改正。 – 2012-03-31 03:03:53

+0

-1,因爲答案包含非真實陳述,並且通常是一個錯誤的解決方案,可能會混淆和誤導XPath的學習者。 – 2012-03-31 04:09:06

0

XSLT1不完全支持的結果樹片段。做你正在嘗試的需要exsl:node-set()

此外,即使在XSLT2,正確的XPath是$DealNode/Deal/Trades/Trade

3

目前接受的答案有一個嚴重的問題。如果它的XPath表達式對下面的XML文檔評價:

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

說明:正確的基因當我們要選擇$ns1在條件$condtrue(),並選擇$ns2$cond是假拉爾則表達式中使用,方法是:

$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 
+1

我發現這個答案適用於我(使用XSLT 1.0),而接受的答案沒有。 – 2015-01-21 20:58:15

+0

@ B.Mo,不客氣。 – 2015-01-21 22:19:10