嗨,这是我的XML文件的内容:
<?xml version="1.0" encoding="ISO-8859-1"?>
<mainNode>
<sub time="08:00">
<status id="2">On</status>
<status id="3">Off</status>
</sub>
<sub time="13:00">
<status id="4">On</status>
<status id="7">On</status>
</sub>
<sub time="16:00">
<status id="5">On</status>
<status id="6">On</status>
<status id="7">Off</status>
<status id="8">On</status>
</sub>
<sub time="20:00">
<status id="4">Off</status>
<status id="7">On</status>
</sub>
<sub time="23:59">
<status id="4">On</status>
<status id="7">On</status>
</sub>
</mainNode>
我的程序获取当前时间: 如果我得到15.59,我必须检索下一个子时间(16.00)的所有状态ID:
<sub time="16:00">
<status id="5">On</status>
<status id="6">On</status>
<status id="7">Off</status>
<status id="8">On</status>
</sub>
使用第二个XPath查询,我必须获得前一个子时间(13.00)的所有状态ID。 怎么做?我知道SQL,但我对XPath很新。如果有的话,我也接受网址到严重的XPath资源。谢谢!
答案 0 :(得分:2)
这是丑陋的Xpath 1.0解决方案: -
sub[number((substring-before(@time, ':')) * 60 + number(substring-after(@time, ':'))) > 959][1]
注意959 = 15 * 60 + 59,我相信你可以在你的主叫代码中做。
将该节点作为以下节点访问: -
preceding-sibling::sub[1]
然而,一个实用的常识解决方案是将XML数据加载到一组数据结构中,并使用更适合此任务的语言来查看项目。
答案 1 :(得分:2)
以下是两个解决方案:
这是一对选择所需节点的XPath 1.0个表达式:
/*/*
[translate(@time, ':','')
>
translate('15:59',':','')
][1]
选择时间晚于sub
的第一个15:59
节点。
/*/*
[translate(@time, ':','')
<
translate('15:59',':','')
][last()]
选择选择前sub
15:59
时间的第一个sub
节点。
我们可以在XSLT转换中包含这些并检查是否产生了真正想要的结果:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes"/>
<xsl:template match="/">
First time after 15:59:
<xsl:copy-of select=
"/*/*
[translate(@time, ':','')
>
translate('15:59',':','')
][1]
"/>
First time before 15:59:
<xsl:copy-of select=
"/*/*
[translate(@time, ':','')
<
translate('15:59',':','')
][last()]
"/>
</xsl:template>
</xsl:stylesheet>
在最初提供的XML文档上应用上述转换时:
<mainNode>
<sub time="08:00">
<status id="2">On</status>
<status id="3">Off</status>
</sub>
<sub time="13:00">
<status id="4">On</status>
<status id="7">On</status>
</sub>
<sub time="16:00">
<status id="5">On</status>
<status id="6">On</status>
<status id="7">Off</status>
<status id="8">On</status>
</sub>
<sub time="20:00">
<status id="4">Off</status>
<status id="7">On</status>
</sub>
<sub time="23:59">
<status id="4">On</status>
<status id="7">On</status>
</sub>
</mainNode>
生成了想要的结果:
First time after 15:59:
<sub time="16:00">
<status id="5">On</status>
<status id="6">On</status>
<status id="7">Off</status>
<status id="8">On</status>
</sub>
First time before 15:59:
<sub time="13:00">
<status id="4">On</status>
<status id="7">On</status>
</sub>
请注意以下内容:
使用XPath translate()
函数来消除冒号
在第二个表达式中使用last()
函数
在比较之前无需将时间转换为秒
当用作XML文档的一部分时(例如XSLT样式表,必须转义<
运算符。
在XPath 2.0中我们可以使用以下两个表达式来生成所需的节点:
/*/*[xs:time(concat(@time,':00'))
gt
xs:time('15:59:00')
][1]
选择时间晚于sub
的第一个15:59
节点。
/*/*[xs:time(concat(@time,':00'))
lt
xs:time('15:59:00')
][last()]
选择选择前sub
15:59
时间的第一个sub
节点。
我们可以在XSLT 2.0转换中包含这些并检查是否产生了真正想要的结果:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:output omit-xml-declaration="yes"/>
<xsl:template match="/">
First time after 15:59:
<xsl:copy-of select=
"/*/*[xs:time(concat(@time,':00'))
gt
xs:time('15:59:00')
][1]
"/>
First time before 15:59:
<xsl:copy-of select=
"/*/*[xs:time(concat(@time,':00'))
lt
xs:time('15:59:00')
][last()]
"/>
</xsl:template>
</xsl:stylesheet>
在原始提供的XML文档上应用上述转换时(与第一个解决方案相同),会产生相同的想要结果。
请注意以下内容:
xs:time
中是本机数据类型。但是,为了从xml文档中的值构造xs:time()
,我们必须将缺少的秒部分连接到它们。xs:time
值中可以与“atomic-value comarison operators”进行比较,例如lt
或gt
。答案 2 :(得分:1)
只要时间是HH:MM就像以下一样: (我必须原谅我的语法,因为我只是在不跑步,考虑这个伪x路径):
xmlns:fn="http://www.w3.org/2005/02/xpath-functions"
//sub[fn:compare(@time,'12:59') > 0][1]/status
这应该选择时间大于12:59的所有元素,然后选择第一个元素。
您还可以将值'12:59'作为e xternal parameter传递到xpath评估中。
答案 3 :(得分:0)
如果您自己生成xml,您可以使用整数值(例如,刻度)更改存储时间属性的方式,然后您可以使用类似
的方式进行简单的数值比较//sub[@time > 1389893892]