Вот два решения:
I. XPath 1.0
Это одна пара 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, оператор <
должен быть экранирован .
II. XPath 2.0
В 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-документу (так же, как в первом решении), получается тот же самый желаемый результат.
Примечание следующее:
- В XPath 2.0
xs:time
- это собственный тип данных . Однако для того, чтобы построить xs:time()
из значений в документе xml, мы должны констатировать им недостающую часть секунд.
- В XPath 2.0
xs:time
значения можно сравнивать с " операторами сопоставления атомарных значений " , такими как lt
или gt
.