【问题标题】:Find duplicate sibling with xpath使用 xpath 查找重复的兄弟姐妹
【发布时间】:2012-09-23 00:06:54
【问题描述】:

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

例如:

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

在示例中,xpath 只选择 &lt;node&gt;&lt;another_one&gt;,因为它们出现了不止一次。

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

【问题讨论】:

    标签: xpath duplicates xpath-2.0 siblings


    【解决方案1】:

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

    【讨论】:

    • +1,非常有表​​现力和简洁的答案。但是,先生,我认为可能还有其他方法。
    • @Cylian,总有“其他方式”——我们必须尽量提供最简洁的方式,同时也是一种高效的解决方案。
    • 我真的有点困惑为什么使用/*/*/*,而不仅仅是//*,但是当我惊讶地尝试使用它时,我发现没有结果节点正在选择。为什么会这样? /*/*/* 有什么特别的意义吗?
    • @Cylian, /*/*/* 选择顶部元素的所有孙子元素。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-23
    • 1970-01-01
    • 1970-01-01
    • 2019-05-06
    • 1970-01-01
    相关资源
    最近更新 更多