2012-10-16 153 views
0

在這個平面XML中,我怎樣才能得到公司名稱的「直接父母」? 我指的是Level = 0的元素,是給定公司之前的第一個元素。獲取元素的前一個兄弟元素?

所以考慮到公司的名稱爲V,我需要得到公司Z.

<Companies> 
    <Company> 
    <Name>X</Name> 
    <Level>1</Level> 
    </Company> 
    <Company> 
    <Name>Y</Name> 
    <Level>1</Level> 
    </Company> 
    <Company> 
    <Name>Z</Name> 
    <Level>0</Level> 
    </Company> 
    <Company> 
    <Name>V</Name> 
    <Level>1</Level> 
    </Company> 
</Companies> 

這不是工作?

<xsl:value-of select="Companies/Company[Name='V']/preceding-sibling[Level=0]/last() 
+0

當你說什麼是「不工作」,你應該說什麼,它實際上是幹什麼的,和對比度與您預計什麼做的。 – LarsH

回答

2

在你<xsl:value-of select="...">,你可以改變

Companies/Company[Name='V']/preceding-sibling[Level=0]/last() 

(Companies/Company[Name='V']/preceding-sibling::*[Level=0])[last()] 

注:

  • 的前同輩軸,就像任何軸,必須跟::和節點測試(如*)。
  • last()是不是你想要的位置步驟(雖然它可能是合法的XSLT 2.0 ....我不知道)。相反,你希望它在一個謂詞[]中。謂詞[last()][position() = last()]的簡寫。
  • 我之前在[last()]之前的所有內容之前加上括號的原因是@盧卡斯提到的原因:preceding-sibling::有相反的方向。

所以,如果你說preceding-sibling::*[last()]你會得到相反的順序剛過去的兄弟,即第1跟前同級文件訂購!由於您實際上需要文檔順序中前面的兄弟姐妹上一個,因此您可以像@Lukasz那樣做preceding-sibling::*[1];或者你可以用我做的(...)[last()]。兩者都是有效的。我稍微喜歡後者,我將在下面解釋。

(...)[last()]形式的作品,而不是隻具有preceding-sibling::軸的步驟,因爲括號強制[last()]謂詞應用到整個XPath表達式到這一點。結果,謂詞被應用於一個不受preceding-sibling::軸逆向控制的表達式。因此,我們選擇文檔的順序的最後一個節點(給定集)。

如果沒有括號,在某些XPath表達式,謂詞和軸的關聯性都可以作爲一個驚喜。您必須瞭解一些優先規則。無可否認,我對學習優先規則的細節有點懶。但是我的經驗(在許多編程語言中)一直依賴於不太明顯的解析優先級規則,這是確保您的代碼被下一個出現並嘗試調試或修改它的人員誤解或混亂的好方法。 (常說,「旁邊的人」是我自己,一個月後。)

1

以下XSLT片段將會從所提供的示例XML以前的公司元素:

<xsl:copy-of select="Companies/Company[Name='V']/preceding-sibling::*[1]" /> 

這將是:

<Company> 
    <Name>Z</Name> 
    <Level>0</Level> 
</Company> 

正如你可以看到,我們在訪問第一個節點(*[1]) - 這看起來可能與直覺相反 - 您可以找到更多解釋here

編輯:我不確定是否要考慮Level = 0條件。

+0

回覆:你的「編輯」問題......我相信他的確如此。見OP的第一段。 – LarsH