我有以下简单的xml:
<root>
<item>
<d>2002-05-30T09:00:00</d>
</item>
<item>
<d>2005-05-30T09:00:00</d>
</item>
<item>
<d>2003-05-30T09:00:00</d>
</item>
</root>
现在我想使用XPath找到最小或最大的dateTime节点。
我现在的解决方案是:
/root/item[not(number(translate(./d, 'TZ:-', '.')) <= number(translate(following-sibling::item, 'TZ:-', '.')))][not(number(translate(./d, 'TZ:-', '.')) <= number(translate(preceding-sibling::item, 'TZ:-', '.')))][1]/d
它有效,但是很丑陋而不是很有效率。基本上它将dateTime转换为数字,然后将它们相互比较。我从here改编了这个。
最好的方法是什么?
干杯
新
答案 0 :(得分:11)
如果你事先不知道item
的数量,你就不能在XPath 1.0中了,因为每个函数都有一个no node-set参数,它的参数是第一个节点在节点集中,并且顺序比较运算符不适用于字符串。
在XPath 2.0中,您可以使用:
max(/root/item/d/xs:dateTime(.))
答案 1 :(得分:2)
@ neo,当我测试时,你列出的的XPath表达不起作用。尝试使用其他数据集,您会看到:
<root>
<item>
<d>2003-05-30T09:00:00</d>
</item>
<item>
<d>2002-05-30T09:00:00</d>
</item>
<item>
<d>2005-05-30T09:00:00</d>
</item>
</root>
您的XPath产生2003-05-30T09:00:00
,显然不是最大值
因为它不起作用是有意义的,因为translate()函数中的previous-sibling ::和following-sibling :: axes每个只产生一个兄弟。你试图对每个轴上的所有兄弟进行一般性(集合)比较,但是在一般比较运算符有机会完成它之前,translate()的第一个参数必须转换为字符串。 Converting a nodeset to a string ignores all nodes except the first one in document order.
此外,translate(./d, 'TZ:-', '.')
会为您提供2003.05.30.09.00.00
之类的结果。这不是有效数字,超出'5'。您的测试数据仅适用,因为年份各不相同。使用translate(./d, 'TZ:-', '')
可以获得更好的结果,这会产生20030530090000
。
Alejandro说在XPath 1.0中不可能这样做,他可能是对的。让我们试一试,也许即使我们没有成功,我们也会学到一些东西。
接下来,我将尝试使用translate函数之外的一般比较,以便它可以比较整个节点集。像这样天真的尝试:
/root/item[
not(following-sibling::item[
translate($current/d, 'TZ:-', '') <= translate(./d, 'TZ:-', '')])
and not(preceding-sibling::item[
translate($current/d, 'TZ:-', '') <= translate(./d, 'TZ:-', '')])]
然而,这是不完整的,如伪变量$ current所示,它应该引用最外面的项,即所有谓词之外的上下文节点。不幸的是,当内部谓词将另一个上下文压入堆栈时,XPath 1.0没有给我们一种引用外部上下文的方法。
(我似乎记得那些\ XSLT的某些实现,例如可能是MSXML,允许你使用像current(1)
这样的扩展功能来实现这一点,但我现在无法找到相关信息。无论如何你问过XPath解决方案,而current()
不是XPath。)
此时我将同意Alejandro认为在纯粹的标准XSLT 1.0中这是不可能的。
如果您指定了使用XPath的环境,例如XSLT,或Javascript,或XQuery,我们可以建议一种有效的方式来获得所需。如果是XPath 2.0,亚历杭德罗有你的答案。
如果您有XQuery 1.0,它应该支持XPath 2.0,因此您可以使用Alejandro的解决方案,使用doc()来访问您的输入XML文档:
max(doc("myInput.xml")/root/item/d/xs:dateTime(.))
答案 2 :(得分:0)
它适用于我,但我现在正在寻找增强xpath,即以下数据:
<root>
<items>
<item>
<d>2002-05-30T09:00:00</d>
</item>
</items>
<items>
<item>
<d>2005-05-30T09:00:00</d>
</item>
</items>
<items>
<item>
<d>2005-05-30T10:00:00</d>
</item>
</items>
</root>