XSLT1.0 / XPath 1.0 Выбор узлов по диапазону дат. Это вообще возможно? - PullRequest
6 голосов
/ 06 января 2011

Допустим, у меня есть список узлов, которые содержат атрибут datetime, и я хочу выбирать только записи, которые появляются после $ compare-datetime.

<records>
    <record @datetime="2010-01-04T16:48:15.501-05:00"/>
    <record @datetime="2010-01-03T16:48:15.501-05:00"/>
    ...etc...
</records>

В xquery для выбора элементов в пределах датыдиапазон, который я бы сделал

/records/record[xs:dateTime(@datetime) > xs:dateTime($compare-datetime)]

Однако в XSLT 1.0 я испробовал множество различных подходов и много поиска ответов, но мне не повезло, что это сработало.

Я начинаюподумайте, что если не считать синтаксического анализа фактического dateTime целочисленного значения, это не простая задача в xslt.

Я надеюсь, что кто-то может дать мне определенный ответ на этот вопрос, чтобы я мог, по крайней мере, знать, с чем я столкнулся.

Приветствия,

Кейси

Ответы [ 4 ]

6 голосов
/ 06 января 2011

Если даты всегда будут в одном и том же часовом поясе и будут иметь поля фиксированной ширины (постоянное количество цифр в каждом поле), я полагаю, что вы могли бы принять такой подход : удалить пунктуацию, оставивчисла, и сравните числа.

<xsl:variable name="datetime-punctuation" select="'-.:T'" />
<xsl:variable name="stripped-compare-datetime"
  select="number(translate($compare-datetime, $datetime-punctuation, ''))" />

Затем используйте

/records/record[number(translate(@datetime, $datetime-punctuation, ''))
                 > $stripped-compare-datetime)]
5 голосов
/ 06 января 2011

Может быть, это не лучшее решение, но у меня есть это:

Ввод XML:

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="dates.xsl"?>
<records>
    <record datetime="2010-01-04T16:48:15.501-05:00"/>
    <record datetime="2011-01-04T16:48:15.501-05:00"/>
</records>

XSLT:

<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:date="http://exslt.org/dates-and-times"
    extension-element-prefixes="date">
    <xsl:import href="date.difference.template.xsl"/>
    <!-- http://exslt.org/date/functions/difference/date.difference.template.xsl -->
    <xsl:output method="xml" indent="yes"/>        

    <xsl:template match="/*">
        <xsl:copy>
            <result1>
                <xsl:call-template name="date:difference">
                   <xsl:with-param name="start" select="record[1]/@datetime"/>
                   <xsl:with-param name="end" select="'2010-04-04T16:48:15.501-05:00'"/>
                </xsl:call-template>
            </result1>
            <result2>
                <xsl:call-template name="date:difference">
                   <xsl:with-param name="start" select="record[2]/@datetime"/>
                   <xsl:with-param name="end" select="'2010-04-04T16:48:15.501-05:00'"/>
                </xsl:call-template>
            </result2>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

Результат:

<records>
    <result1>P90D</result1>
    <result2>-P275D</result2>
</records>

Отрицательная разница будет означать, что первая дата происходит после второй даты.

1 голос
/ 06 января 2011

Боюсь, что XSLT 1.0 не имеет встроенной поддержки dateTimes. Возможно, вы обнаружите, что кто-то написал библиотеку - посмотрите FAQ по XSLT

См. http://www.dpawson.co.uk/xsl/rev2/dates.html#d14938e16, что XSLT 2.0 может предложить.

0 голосов
/ 12 марта 2011

У меня была такая же проблема, как и у вас. Я создал метод C # (поэтому он работает только с .Net XSLT):

<msxsl:script language="C#" implements-prefix="user">
  <![CDATA[
   public bool largerThan(DateTime dt0, DateTime dt1) {
     return dt0 > dt1;
   }
    ]]>
</msxsl:script>

с пространствами имен

xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:user="urn:my-scripts"

и использование (фрагмент из моего документа xslt)

<xsl:for-each select="../b:post[user:largerThan(@created,$created)]">
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...