2009-12-31 160 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())