如何仅使用Xpath查找至少具有相似/相等兄弟节点的节点?
例如:
<root>
<parent>
<node>...</node>
<node_unique>...</node_unique>
<node>...</node>
<another_one>...</another_one>
<another_one>...</another_one>
</parent>
</root>
在示例中,xpath shold仅选择<node>
和<another_one>
,因为它们不止一次出现。
我试图找到一个解决方案几个小时没有成功(现在我认为XPath不可能......)。
答案 0 :(得分:5)
使用单个XPath 1.0表达式无法选择(由于XPath 1.0中缺少范围变量)。
一种可能的解决方案是选择所有/*/*/*
元素,然后使用name()
关闭该元素来获取每个元素的名称,然后评估/*/*/*[name() = $currentName][2]
(其中$currentName
应该用刚刚获得的名称替换。如果最后一个表达式选择一个元素,那么currentName
是一个至少出现两次的名称 - 因此你保留该元素。对所有元素及其名称这样做。作为一个辅助步骤,人们可以通过将它们放在哈希表中来重复删除名称(和所选元素)。
在Xpath 2.0中,使用单个XPath表达式选择给定父级的所有子级,其中至少有一个具有相同名称的其他兄弟,这是微不足道的:
/*/*/*
[name() = following-sibling::*/name()
and
not(name() = preceding-sibling::*/name())
]
更紧凑的表达:
/*/*/*[index-of(/*/*/*/name(), name())[2]]
基于XSLT 2.0的验证:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/">
<xsl:copy-of select=
"/*/*/*[index-of(/*/*/*/name(), name())[2]]"/>
</xsl:template>
</xsl:stylesheet>
在提供的XML文档上应用此转换时:
<root>
<parent>
<node>...</node>
<node_unique>...</node_unique>
<node>...</node>
<another_one>...</another_one>
<another_one>...</another_one>
</parent>
</root>
评估上述XPath表达式,并将从此评估元素中选择的内容复制到输出:
<node>...</node>
<another_one>...</another_one>
注意:有关相关问题/答案,请参阅 this 。