使用xpath选择具有最大属性值的节点

3

给定这样一个xml文档:

<node>
  <node text="text1" x=400 y=400></node>
</node>
<node>
  <node text="text1" x=400 y=900></node>
</node>
<node>
  <node text="text2" x=400 y=1000></node>
</node>
... etc ...

我应该如何编写xpath查询来选择文本属性为"text1"且y值最大(在此情况下为900)的节点? 我不知道y值将是多少,但我知道我总是要选择具有更高y值的节点,并且这两个节点不会是兄弟节点。 除了y值之外,我试图区分的这两个节点将具有所有相等的属性。

1个回答

4

您输入的文档格式不正确。它缺少唯一的最外层(根)元素,并且某些属性值没有引号。给定一个像这样格式正确的输入文档:

<root>
<node>
  <node text="text1" x="400" y="400"></node>
</node>
<node>
  <node text="text1" x="400" y="900"></node>
</node>
<node>
  <node text="text2" x="400" y="1000"></node>
</node>
</root>

The following XPath expression:

//node[@text = 'text1' and not(@y < preceding::node[@text = 'text1']/@y or @y < following::node[@text = 'text1']/@y)]

查找具有text1和@y中最高值的node元素。在这种情况下,唯一的结果是

<node text="text1" x="400" y="900"/>

更详细地说,路径表达式意味着:
//node                                              select all `node` elements, anywhere in
                                                    the document
[@text = 'text1'                                    but only if its `text` attribute is
                                                    equal to "text1"
and not(@y < preceding::node[@text = 'text1']/@y    and only if the value of its `y`
                                                    attribute is not lower than the value
                                                    of an `y` attribute of another `node`
                                                    element of the same sort that precedes
                                                    the current one
or @y < following::node[@text = 'text1']/@y)]       and only if the value if its `y`
                                                    attribute is not lower than the value
                                                    of an `y` attribute of another `node`
                                                    element of the same sort that follows
                                                    the current one

编辑:或者,使用

//node[@text="text1" and not(//node[@text="text1"]/@y > @y)]

正如splash58所建议的那样。这个表达式的语义与上面的表达式非常相似。

不错,是的,我只是手工把它拼凑在一起的。我会尝试那个解决方案! - Patrick Grayson
@user3174484 如果它有效,请告诉我。如果无效,您可能已经省略了一些重要的内容,并需要展示更多实际输入文档的内容。 - Mathias Müller
@MathiasMüller //node[@text="text1" and not(//node[@text="text1"]/@y > .//@y)] - 这样更短。这不正确吗? - splash58
@splash58 是的,没错。感谢您的建议 - 我会将其添加到我的答案中。 - Mathias Müller
@splash58 P.s. 可以更短一些,因为可以使用 @y 代替 .//@y - Mathias Müller

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接