2009-12-31 158 views
5

我想使用XPath獲取XML文件中出現的所有元素的名稱列表。但是,我不想重複任何名稱,因此與前一個元素具有相同名稱的元素不應匹配。到目前爲止,我得到了:獲取唯一元素名稱的XPath

*[not(local-name() = local-name(preceding::*))] 

這個執行正常,但它吐出重複。它爲什麼會吐出重複的東西,我如何消除它們? (我正在使用Firefox的XPath引擎。)

+0

您的代碼吐奶因爲列表沒有排序,所以沒有重複。它可以在有序列表上工作。 – 2014-12-19 03:39:47

回答

5

您正在獲取重複項,因爲您的篩選器未評估您的想法。

本地名稱()函數返回節點集的第一節點的本地名稱。

您的謂詞過濾器唯一的工作方式是該元素碰巧與第一個元素具有相同的名稱。

我不認爲你能夠完成你想要的純粹的XPATH 1.0靈魂。你可以在XPATH 2.0中做到這一點,但這不適用於Firefox。

XSLT可以使用meunchien method來完成你想要的東西。

下面是一個例子。您沒有提供任何示例XML,所以我一直是非常通用的(如// *在文檔的所有元素相匹配):

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"><xsl:output method="xml"/> 
<xsl:key name="names" match="//*" use="local-name(.)"/> 
<xsl:template match="/"> 
    <xsl:for-each select="//*[generate-id(.) = generate-id(key('names', local-name(.)))]"> 
     <!--Do something with the unique list of elements--> 
    </xsl:for-each> 
</xsl:template> 
</xsl:stylesheet> 
+0

感謝您的線索。關於返回第一個節點的local-name()是正確的。我其實打算將此標記爲接受的答案,但點擊了錯誤的選中標記。但是,我最終做了JavaScript中的過濾,所以這兩個答案都是我的解決方案的一部分。謝謝。 – mawrya 2010-01-05 19:29:35

1

我建議先獲取所有元素的列表,然後遍歷列表並將它們添加到字典中以檢測重複項。

例如,在僞碼:

var allElements = doc.select("//node()"); 
var distinctElementTypes = new object(); 
foreach (var elem in allElements) { 
    distinctElementTypes[elem.name] = elem.name; 
} 

現在distinctElementTypes將是不同的元素名稱的字典。

+0

感謝您的回覆。我可以採取這種方法,但xpath只需要一行代碼。此外,這正是xpath所針對的問題的類型。我想知道給出的例子有什麼問題,因爲我想進一步進行xpath教育。據我所知,它應該工作,但事實並非如此。 – mawrya 2009-12-31 23:53:01

+0

我不知道爲什麼'之前'不工作。難道它只是比較所討論的節點的前面的兄弟節點而不是所有*前面的節點? – Eilon 2010-01-01 01:45:49

+0

這將是之前的兄弟::軸。 W3C認爲: 上一軸包含與文檔順序中上下文節點相同的文檔中與上下文節點相同的所有節點,排除了任何祖先並排除了屬性節點和名稱空間節點。 所以,我明白了爲什麼我可能會得到重複,如果具有相同名稱的元素是祖先,但我也從兄弟元素得到重複! – mawrya 2010-01-01 03:23:44

6

XPath 2.0中有效:

distinct-values(//*/name())