2012-04-09 1 views
2

Мне нужно получить список дат между двумя датами - например, У меня есть дата 03302012 и 05302012 ENDDATE начала и мне нужен выход, какXSLT 1.0: Получить список дат между двумя датами, используя XSLT

 
03302012 
03312012 
04012012 
04022012 
... 
05282012 
05292012 
05302012 
  • Вы можете использовать формат даты - я буду делать преобразование сам. Большое спасибо!
+0

привет, Не забудьте принять ответ. –

ответ

2

Вы можете сделать это, используя рекурсивный шаблон. Это не лучшее решение, так как это подвержено переполнению стека или ошибкам памяти (если заданный вами интервал дат достаточно велик), но это может быть место для начала.

Первое, что вам нужно для приведенного ниже примера, - проверить способ сгенерированного значения и убедиться, что это действительная дата (для этого вы можете найти несколько примеров в Интернете: я просто использовал a sample from an open source project и импортировал файл в примере только для держите его короче).

Тогда идея состоит в том, чтобы сгенерировать даты, добавив день к предыдущему, а затем день к текущему и так далее. Если день переполняется, вы добавляете один из них в месяц и начинаете снова с 1-го дня. Если переполнение месяца вы делаете то же самое с годом и начинаете с месяца 1. Теоретически единственным, который никогда не переполняется, является год (но вы ограничите это с конечным значением интервала).

Вы создаете дату и подтверждаете ее. Если он действителен и не дошел до конца интервала, который вы пытаетесь сгенерировать другим, добавив к нему дни (это то, что происходит в блоке X).

Когда вы получаете недопустимое значение, тогда что-то переполняется. Это может быть только день или месяц (как я уже упоминал выше). Сначала я проверяю месяц (блок Y). Если это так, я начинаю с 1-го числа месяца 1, но на следующий год. Если это день, который переполнен (блок Z), я начинаю с первого дня следующего месяца.

<?xml version="1.0" encoding="utf-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

    <xsl:import href="http://www.getsymphony.com/download/xslt-utilities/source-code/54294/"/> 
    <xsl:output method="xml" omit-xml-declaration="yes" encoding="UTF-8" indent="yes" /> 

    <xsl:variable name="startDate" select="'03302012'" /> <!-- MMddyyyy format --> 
    <xsl:variable name="endDate" select="'05302012'" /> <!-- MMddyyyy format --> 

    <xsl:template match="/"> 
    <values> 
     <xsl:call-template name="GenerateList"> 
     <xsl:with-param name="day" select="number(substring($startDate, 3, 2))" /> 
     <xsl:with-param name="month" select="number(substring($startDate, 1, 2))" /> 
     <xsl:with-param name="year" select="number(substring($startDate, 5))" /> 
     </xsl:call-template> 
    </values> 
    </xsl:template> 

    <xsl:template name="GenerateList"> 
    <xsl:param name="day" select="1" /> 
    <xsl:param name="month" select="1" /> 
    <xsl:param name="year" select="1" /> 

    <!-- 1 = valid, 0 = invalid according to the imported file --> 
    <xsl:variable name="validationResult"> 
     <xsl:call-template name="date-is-valid"> 
     <xsl:with-param name="day" select="$day"/> 
     <xsl:with-param name="month" select="$month"/> 
     <xsl:with-param name="year" select="$year"/> 
     </xsl:call-template> 
    </xsl:variable> 

    <xsl:choose> 
     <xsl:when test="$validationResult = 0"> 

     <xsl:choose> 
      <xsl:when test="$month &gt; 12"> 
      <!-- block Y --> 
      <xsl:call-template name="GenerateList"> 
       <xsl:with-param name="day" select="1" /> 
       <xsl:with-param name="month" select="1" /> 
       <xsl:with-param name="year" select="$year + 1" /> 
      </xsl:call-template> 
      </xsl:when> 
      <xsl:otherwise> 
      <!-- block Z --> 
      <xsl:call-template name="GenerateList"> 
       <xsl:with-param name="day" select="1" /> 
       <xsl:with-param name="month" select="$month + 1" /> 
       <xsl:with-param name="year" select="$year" /> 
      </xsl:call-template> 
      </xsl:otherwise> 
     </xsl:choose> 

     </xsl:when> 
     <xsl:otherwise> 
     <!-- block X --> 
     <!-- same MMddyyyy format as the interval values --> 
     <xsl:variable name="currentDate" select="concat(format-number($month, '00'), format-number($day, '00'), $year)" /> 
     <value> 
      <xsl:value-of select="$currentDate" /> 
     </value> 
     <xsl:if test="not($currentDate = $endDate)"> 
      <xsl:call-template name="GenerateList"> 
      <xsl:with-param name="day" select="$day + 1" /> 
      <xsl:with-param name="month" select="$month" /> 
      <xsl:with-param name="year" select="$year" /> 
      </xsl:call-template> 
     </xsl:if> 

     </xsl:otherwise> 
    </xsl:choose> 

    </xsl:template> 
</xsl:stylesheet> 
+0

Спасибо, Богдан! Это круто и работает для меня! –

0

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

  1. Самое простое решение, как правило, чтобы сделать такой список часть входа =)

  2. Преобразование в XSLT обычно является частью более широкого применения с конкретными XSLT, который позволяет использовать определенные средства для его расширения. Вы можете написать функцию расширения (используя Java, Javascript, PHP, Python в зависимости от процессора), которая возвращает требуемый набор узлов. Другой, но аналогичный вариант - зарегистрировать «поток» (с точки зрения как минимум PHP) и получить набор узлов, используя функцию document с URL-адресом, например app://Dates/listdates?start=a&end=b. Недостатком является то, что таблица стилей связана с приложением и не может быть разработана отдельно.

  3. Большинство процессоров XSTL поддерживают расширения EXSLT. Вы можете вычислить количество дней между датами с использованием модификаций дат, сгенерировать строку длины, используя функциюиз строки расширения, разделить строку на пустую строку, чтобы получить список токенов (требуемой длины) и перебрать по списку используя функцию node-set и добавив текущую позицию узла к первой дате, используя date-add.

  4. Используйте чистые XSLT и рекурсивные шаблоны, как предлагает Богдан.