XPath 3.0:select 个条件节点(按日期查找最大子节点)
XPath 3.0: select nodes by condition (find max child nodes by date)
给定 XML:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<c cid="c0" v="100">
<d did="c00" v="0" dt="2016-01-01" />
<d did="c01" v="0" dt="2016-02-03" />
<d did="c02" v="0" dt="2016-01-15" />
</c>
<c cid="c1" v="100">
<d did="c10" v="1" dt="2016-01-01" />
<d did="c11" v="0" dt="2015-03-03" />
<d did="c12" v="0" dt="2015-04-15" />
</c>
</root>
我必须找到 XPath 2.0 或 3.0,它将 return 给我 c
节点的列表 c
表达式:找到这个 c
子节点的最大 d
节点通过 dt
属性(将其解析为 date
),如果其 v
属性值为“0”,则 return 为 c
节点。
我希望得到一个 c
节点(@cid="c0")作为结果,因为 /root/c[cid="c1"]/d[@dt="2016-01-01"]/@v
不等于 0(等于 1)。
到目前为止,我一直坚持这个 XPath:
/root/c[d[max(xs:date(@dt))]/@v="0"]
它给我一个错误(我正在使用 Oxygen XML 编辑器,XPath 3.0):
XPath failed due to: Effective boolean value is not defined for a
sequence starting with an atomic value other than a boolean, number,
string, or URI
我想这是由于误用了 max
功能,但无法使其正常工作。
更新:
- 让我们假设
c
个节点将有 d
个具有其 dt
属性的唯一最大值的子节点。
我也试过 XPath 3.0 表达式:
/root/c[d[@dt=max(.//@dt/xs:date(.))]/@v="0"]
但它 return 告诉我所有节点(错误结果)。
在 XQuery 中,查询非常简单,可以编写为每个 c
节点只计算一次最大日期:
for $c in /root/c
let $max := max($c/d/@dt/xs:date(.))
where $c/d[@dt = $max]/@v = '0'
return $c
在 XPath 中,您可以编写查询(至少在概念上)对每个 d
节点计算一次,并希望结果要么被处理器优化,要么无论如何都足够快:
/root/c[d[@dt = max(../d/@dt/xs:date(.))]/@v = '0']
也可以使用XPath的let
expression恢复显式预计算:
/root/c[
let $max := max(d/@dt/xs:date(.))
return d[@dt = $max]/@v = '0'
]
这是一个更短且可能更有效的(每个<c>
元素的最大值只计算一次)XPath 2.0 一行:
/*/c[max(d/xs:date(@dt)) = d[@v eq '0']/@dt]
尽情享受吧!
给定 XML:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<c cid="c0" v="100">
<d did="c00" v="0" dt="2016-01-01" />
<d did="c01" v="0" dt="2016-02-03" />
<d did="c02" v="0" dt="2016-01-15" />
</c>
<c cid="c1" v="100">
<d did="c10" v="1" dt="2016-01-01" />
<d did="c11" v="0" dt="2015-03-03" />
<d did="c12" v="0" dt="2015-04-15" />
</c>
</root>
我必须找到 XPath 2.0 或 3.0,它将 return 给我 c
节点的列表 c
表达式:找到这个 c
子节点的最大 d
节点通过 dt
属性(将其解析为 date
),如果其 v
属性值为“0”,则 return 为 c
节点。
我希望得到一个 c
节点(@cid="c0")作为结果,因为 /root/c[cid="c1"]/d[@dt="2016-01-01"]/@v
不等于 0(等于 1)。
到目前为止,我一直坚持这个 XPath:
/root/c[d[max(xs:date(@dt))]/@v="0"]
它给我一个错误(我正在使用 Oxygen XML 编辑器,XPath 3.0):
XPath failed due to: Effective boolean value is not defined for a sequence starting with an atomic value other than a boolean, number, string, or URI
我想这是由于误用了 max
功能,但无法使其正常工作。
更新:
- 让我们假设
c
个节点将有d
个具有其dt
属性的唯一最大值的子节点。 我也试过 XPath 3.0 表达式:
/root/c[d[@dt=max(.//@dt/xs:date(.))]/@v="0"]
但它 return 告诉我所有节点(错误结果)。
在 XQuery 中,查询非常简单,可以编写为每个 c
节点只计算一次最大日期:
for $c in /root/c
let $max := max($c/d/@dt/xs:date(.))
where $c/d[@dt = $max]/@v = '0'
return $c
在 XPath 中,您可以编写查询(至少在概念上)对每个 d
节点计算一次,并希望结果要么被处理器优化,要么无论如何都足够快:
/root/c[d[@dt = max(../d/@dt/xs:date(.))]/@v = '0']
也可以使用XPath的let
expression恢复显式预计算:
/root/c[
let $max := max(d/@dt/xs:date(.))
return d[@dt = $max]/@v = '0'
]
这是一个更短且可能更有效的(每个<c>
元素的最大值只计算一次)XPath 2.0 一行:
/*/c[max(d/xs:date(@dt)) = d[@v eq '0']/@dt]
尽情享受吧!