2013-03-28 45 views
4

我有一個XML這就好比是選擇節點的第一次出現:如何使用XSLT

<bookstores> 
    <bookstore> 
     <book id="1"> 
      <author>ABC</author> 
     </book> 
     <book id="2"> 
      <title>YYY</title> 
     </book> 
    </bookstore> 
    <bookstore> 
     <book id="3"> 
      <author>ABC</author> 
     </book> 
     <book id="4"> 
      <author>DEF</author> 
     </book> 
    </bookstore> 
    <bookstore> 
     <book id="5"> 
      <price>50</price> 
     </book> 
     <book id="6"> 
      <title>ZZZ</title> 
     </book> 
    </bookstore> 
</bookstores> 

我想選擇「書」節點的孩子或者換句話說,第一次出現,'book'節點的所有獨特的子節點。

所以輸出應該是這樣的:

author 
title 
price 

我寫了一個XSLT爲:

<xsl:for-each select="bookstores/bookstore/book"> 
    <xsl:if test="count(preceding-sibling::*[1]) = 0"> 
     <xsl:value-of select="local-name(*[1])"/> 
    </xsl:if> 
</xsl:for-each> 

這回我什麼...任何人都可以給我一些這方面的幫助?謝謝!!

UPDATE:

如果我有幾個「書店」在我的XML元素,我只是想給每個「書店」範圍內限制了獨特因此,即使「作者」出現在一個「書店」,如果它出現在另一家「書店」中,它仍然可以顯示出來?

+0

您使用的是XSLT 1.0還是XSLT 2.0? –

回答

3

,讓不同元素的方法是通過一個叫Muenchian分組的技術。你的情況,你要「羣」的書子元素,因此,開始時,你定義了一個關鍵的元素名稱來查找圖書的子元素

<xsl:key name="child" match="book/*" use="local-name()" /> 

爲了得到不同的名稱,你再查看所有書籍子元素,但僅輸出組中名稱首次出現的元素。你這個使用這個可怕的語句來做到:

<xsl:apply-templates 
    select="//book/*[generate-id() = generate-id(key('child', local-name())[1])]" /> 

以下是完整的XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="text"/> 
    <xsl:key name="child" match="book/*" use="local-name()" /> 

    <xsl:template match="/"> 
     <xsl:apply-templates select="//book/*[generate-id() = generate-id(key('child', local-name())[1])]" /> 
    </xsl:template> 

    <xsl:template match="//book/*"> 
     <xsl:value-of select="concat(local-name(), '&#10;')" /> 
    </xsl:template> 
</xsl:stylesheet> 

當適用於您的XML,下面是輸出

author 
title 
price 
+0

謝謝!我試過了,得到了我想要的!更重要的是,現在我已經獲得了有關Muenchian Grouping的新知識。非常感謝! –

-1

您可以使用 <xsl:for-each select="//book">如果使用XSLT1.0選擇occurances

2

稍短/簡單 - - 完全處於「推式」:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output method="text"/> 
<xsl:key name="kBChildrenByName" match="book/*" use="name()"/> 

<xsl:template match= 
    "book/*[generate-id()=generate-id(key('kBChildrenByName', name())[1])]"> 
    <xsl:value-of select="concat(name(), '&#xA;')"/> 
</xsl:template> 
<xsl:template match="text()"/> 
</xsl:stylesheet> 

當該變換被應用到所提供的XML文檔:

<bookstores> 
    <bookstore> 
     <book id="1"> 
      <author>ABC</author> 
     </book> 
     <book id="2"> 
      <title>YYY</title> 
     </book> 
    </bookstore> 
    <bookstore> 
     <book id="3"> 
      <author>ABC</author> 
     </book> 
     <book id="4"> 
      <author>DEF</author> 
     </book> 
    </bookstore> 
    <bookstore> 
     <book id="5"> 
      <price>50</price> 
     </book> 
     <book id="6"> 
      <title>ZZZ</title> 
     </book> 
    </bookstore> 
</bookstores> 

有用,正確的結果產生:

author 
title 
price 

說明

適當使用的Muenchian grouping method

+0

謝謝你的回答。我可以問一個愚蠢的問題嗎?什麼是concat()函數的第二個參數? –

+0

@ D.Q。在這種情況下,第二個參數是一個由單個字符組成的字符串,其(Unicode)代碼是數字「10」或十六進制「A」。這實際上是新線人物。 –

+0

謝謝您的解釋!並感謝您的回答以及您提供的鏈接,這絕對有用!由於蒂姆先前回答了我的問題,我接受了他的回答。我非常感謝你的幫助! –