2011-06-07 72 views
0

我無法顯示第一個匹配值,如找到第一個匹配時,打破每個循環的XSLT

<test> 
    <p>30</p> 
    <p>30{1{{23{45<p> 
    <p>23{34</p> 
    <p>30{1{98</p> 
</test> 
<test2> 
    <p1>text</p1> 
</test2> 

所以我想循環遍歷<test></test>並找到字符串長度大於2且包含30的<p>節點的值。我只想要第一個值。 所以我累了下面的代碼

<xsl:variable name="var_test"> 
    <xsl:for-each select="*/*/test()> 
     <xsl:if string-length(p/text())>2 and contains(p/text(),'30')) 
    <xsl:value-of select="xpath"> 
</xsl:variable> 

問題是var_test始終爲null。

如果我直接嘗試任何變量

<xsl:for-each select="*/*/test()> 
    <xsl:if string-length(p/text())>2 and contains(p/text(),'30')) 
<xsl:value-of select="xpath"> 

我得到以下輸出

<p>30{1{23{4530{1{98</p> 

但是所需的輸出是

<p>0{1{23{45</p> 

所以我怎麼能實現這個?

+1

您的問題中仍然存在相當多的拼寫錯誤,您可能需要解決此問題。 – LarsH 2011-06-07 21:25:40

+1

'xpath'有一些我沒有聽說過的特殊價值嗎?似乎有很多「壞xslt mojo」在這裏進行。謹慎處理.... – 2011-06-07 21:28:47

+0

@Abe:很好的問題。不,它不是一個特殊的關鍵字或任何東西。在這裏它將被解釋爲一個子元素的名稱 - 其中沒有。我想知道OP的含義。 – LarsH 2011-06-07 21:32:28

回答

3

相反的的for-each,使用

<xsl:copy-of select="(*/*/test/p[string-length() > 2 and 
           contains(.,'30'))])[1]" /> 

[1]只選擇第一匹配<p>。 (更新:我改變上述的XPath響應@ markusk的評論)

上面會輸出如在「所需的輸出」 <p>元素以及它的文本內容。如果您實際上只需要<p>的值(即其文本內容),請使用<xsl:value-of>而不是<xsl:copy-of>

附錄:

打破了一個循環並不適用於XSLT,因爲它是不是程序語言的想法。在<xsl:for-each>循環中,循環的「第一個」實例化(根據文檔順序或排序順序)並不一定在「最後」實例化之前的時間順序上進行評估。他們可能會以任何順序或平行進行評估,因爲他們不相互依賴。因此,試圖「跳出循環」,意圖導致循環的「後續」實例化不能被評估,如果這樣做,後來的實例化的結果將依賴於較早的實例化,並行評估將被排除。

+0

好dec! – 2011-06-07 21:51:07

+1

您的表達式在每個「test」節點中選擇第一個匹配的「p」節點。如果有多個'test'節點,則表達式可能會返回多個'p'節點。爲了確保您最多隻能獲得一個節點,您需要編寫'(*/*/test/p [string-length()> 2幷包含(。,'30')])[1]'。 – markusk 2011-06-07 22:46:22

+0

@markusk:你有一個好點。我的問題是,我還不清楚OP是否希望每個測試節點有一個匹配的'p'節點,或者整個匹配'p'。但我認爲你的解釋是對的。我會改變我的答案。 @Newbie – LarsH 2011-06-08 14:34:05