所有元素的XPath,但我们只在重复名称的人中获取第一个匹配项

时间:2012-07-12 12:58:03

标签: xml xpath xquery distinct nodes

它应该返回具有相同名称的节点的所有第一次出现,即使子节点和属性不同。

例如

<Data>
  <A>
    <X randomattr="1"/>
    <Y randomattr="1"/>
    <Z/>
  </A>
  <B>
    <X/>
    <X randomattr="3"/>
    <Z/>
  </B>
</Data>

它可以返回3个节点,首先是X,Y和Z,因为以下内容将有一个重复的名称。不要介意其中一个X元素没有randomattr,或者另一个元素是否有不同的值。

我不想要name()中的distinct-values,我想返回整个节点。像

这样的东西
/Data/*/*[distinct-values(name())]

我也知道我可以使用双循环遍历所有节点,但我问我自己是否有一个简单的单行或函数,或者特殊的Xpath语法,如distinct [1] 谢谢你!

2 个答案:

答案 0 :(得分:0)

我认为这是你可能正在寻找的东西。进行了一些简单的测试:

  • (Xpath 2.0)/Data/*/*[not((preceding-sibling::*/name(.)=name(.)) or (../preceding-sibling::*/*/name(.)=name(.)))]
  • (Xpath 1.0)/Data/*/*[not((name(preceding-sibling::*)=name(.)) or (name(../preceding-sibling::*/*)=name(.)))]

请求使其工作到任何深度...我不熟悉您的架构,但从示例我假设您正在寻找的节点是底层节点。以下使用后代轴在进行名称检查时搜索没有子节点的节点。

  • /Data/descendant::*[not(name() = preceding::*[not(child::*)]/name())][not(child::*)]

答案 1 :(得分:0)

我会永远接受错误的问题,但我从我从他那里学到的东西回答了另一种可能性,并且在我用AXES进行一些研究后,我才刚刚学到了这些东西。

/Data/*/*[not(name() = preceding::*[name(../..)='Data']/name())]

(名字()也可以是自语:: * / name(),语法如下)

对于任何上下文,这都是我认为更容易和最好的线,因为当叶级很深时,它不会呈指数级复杂增长。只需更改先例上的条件以匹配'from-root'兄弟,如[name(../..)='Data']或定义此层次结构级别的所有节点的条件,或者如果它们共享则在:: name_node之前相同的qname