2

如何使用 Xpath 仅查找具有至少相似/相等同级节点的节点?

例如:

<root>
  <parent>
    <node>...</node>
    <node_unique>...</node_unique>
    <node>...</node>
    <another_one>...</another_one>
    <another_one>...</another_one>
  </parent>
</root>

在示例中,xpath 仅支持选择<node><another_one>因为它们出现了不止一次。

我试图为此找到一个解决方案几个小时而没有成功(现在我认为 XPath 是不可能的......)。

4

1 回答 1

6

这些是不可能用单个 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>

注意:有关相关问题/答案,请参阅

于 2012-09-23T04:14:24.073 回答