2008-10-22 51 views
13

我發現this page描述了Muenchian方法,但我認爲我錯誤地應用了它。如何選擇獨特節點

認爲這將返回一組年齡:

/doc/class/person/descriptive[(@name='age')]/value 

1..2..2..2..3..3..4..7

但我想每個年齡節點集只有一個節點。

1..2..3..4..7

每一種似乎回到所有的值,而不是唯一值:

/doc/class/person/descriptive[(@name='age')][not(value=preceding-sibling::value)]/value 
/doc/class/person/descriptive[(@name='age')]/value[not(value=preceding-sibling::value)] 

上午什麼我錯過了?

+0

糟糕,它看起來像例如我其次是*不是* Muenchian方法 - 而是作者反對它。 – pc1oad1etter 2008-10-22 22:13:37

回答

20

下面是一個例子:

<root> 
    <item type='test'>A</item> 
    <item type='test'>B</item> 
    <item type='test'>C</item> 
    <item type='test'>A</item> 
    <item type='other'>A</item> 
    <item type='test'>B</item> 
    <item type='other'>D</item> 
    <item type=''>A</item> 
</root> 

而且XPath的:

//preceding::item/preceding::item[not(.=preceding-sibling::item)]/text() 

結果: ABCD

編輯: 由於mousio評論說,如果它是唯一出現的時間,它不會捕獲列表中的最後一項。考慮這一點,考慮F隺nor的評論,這裏有一個更好的解決方案:

/root/item[not(.=preceding-sibling::item)] 
+0

很明顯,您可以使用額外的XPath根據實際文件中的類型屬性或其他數據進行限制。在我的快速測試中,我剛剛在那裏。 – 2008-10-22 22:47:30

+0

另請注意,XPath中的「item」不是關鍵字,它是前面的::和之前的 - sibling ::軸正在處理的XML文檔中元素的名稱。 – 2008-10-22 22:50:55

1

您是否錯過前面的值之後引用'描述性'?有些東西像下面這樣:

/doc/class/person/descriptive[(@name='age')][not(value=preceding-sibling::descriptive[@name='age']/value)]/value 

(沒有測試過)

14

下面是使用他的數據BQ的答案的Muenchian版本:

<?xml version="1.0"?> 
<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

    <xsl:output indent="yes" method="text"/> 
    <xsl:key name="item-by-value" match="item" use="."/> 

    <xsl:template match="/"> 
    <xsl:apply-templates select="/root/item"/> 
    </xsl:template> 

    <xsl:template match="item"> 
    <xsl:if test="generate-id() = generate-id(key('item-by-value', normalize-space(.)))"> 
     <xsl:value-of select="."/> 
     <xsl:text> 
</xsl:text> 
    </xsl:if> 
    </xsl:template> 

    <xsl:template match="text()"> 
    <xsl:apply-templates/> 
    </xsl:template> 
</xsl:stylesheet> 

這種轉變給

一個

C
D

  1. key()item的模板中查找上面返回的節點集包含與上下文節點具有相同字符串值的所有item元素。
  2. 如果您將一個需要單個節點的函數應用於節點集,它將在該節點集中的第一個節點上運行。
  3. 所有對generate-id()的調用都保證在單次傳遞文檔期間爲給定節點生成相同的ID。
  4. 因此,如果上下文節點與key()調用返回的第一個節點是相同的節點,則測試將爲真。
2

Muenchian方法使用鍵來創建節點集中項目的唯一列表。爲您的數據,關鍵是這樣的:

<!-- Set the name to whatever you want --> 
<xsl:key name="PeopleAges" match="/doc/class/person/descriptive[@name = 'age']/value" use="." /> 

從那裏,我會親自使用xsl:apply-templates但你可以用在其他地方以下select屬性:

<!-- you can change `apply-templates` to: `copy-of` or `for-each`. --> 
<xsl:apply-templates select="/doc/class/person/descriptive[@name = 'age']/value[count(. | key('PeopleAges', .)[1]) = 1]" /> 

所附難擋以上是簡單得多:

<xsl:template match="person/descriptive[@name = 'age']/value"> 
    <strong>Age: </strong><xsl:value-of select="." /> 
</xsl:template> 
3

對於那些誰仍在尋找一個SELECT DISTINCT在XSLT:

使用XSLT 2.0, 可以使用 「不同的值(/ DOC /類/人/描述[(@名= '年齡')] /值)」