XSLT - совпадение и групповое время - PullRequest
0 голосов
/ 01 марта 2019

Я пытаюсь создать некоторые расписания на основе XML ниже.Это фиктивные данные, поэтому игнорируйте огромные промежутки во времени.По сути, когда код дня соответствует 0, как показано ниже, мне нужно вытащить все значения ТОЛЬКО после полуночи (00:00), отбросить остаток и увеличить день + 1. Однако, если время входа и выхода перекрывается в полночь,например, 1755-0115 в приведенном ниже примере, тогда мне все еще нужно захватить время в тот же день в файле, но жестко закодировать 1755 как 00:01 и все еще увеличивать на один день.Все остальное до полуночи все еще отбрасывается.Все блоки всегда будут в порядке, и самые ранние удары (например, 0900) - это утренние удары.

`<Employee>
      <employee_id>123456</employee_id>
      <day_code>0</day_code>
      <day>12-01-18</day>
      <block>
         <in>0900</in>
         <out>1526</out>
      </block>
      <block>
         <in>1526</in>
         <out>1526</out>
      </block>
      <block>
         <in>1526</in>
         <out>1740</out>
      </block>
      <block>
         <in>1740</in>
         <out>1755</out>
      </block>
      <block>
         <in>1755</in>
         <out>0115</out>
      </block>
   <block>
      <in>0115</in>
      <out>0315</out>
   </block>
   </Employee>`

Поэтому мне нужно, чтобы это выглядело так, когда я извлекаю данные.

'<Employee_Schedules>
         <in>12-02-18-T00:01</in>
         <out>12-02-18-T01:15</out>
   <block>
      <in>12-02-18-T01:15</in>
      <out>12-02-18-T03:15</out>
   </block>
   </Employee_Schedules>`

Я думал о проверке двух блоков с использованием предыдущей братской функции.Проверьте, меньше ли время ввода первого блока, чем время выхода второго блока, а второй условно проверяет немедленное, что время немедленного блока меньше времени ожидания, но это не сработало слишком хорошо.

Любая помощь очень ценится!

1 Ответ

0 голосов
/ 01 марта 2019

Я "исправил" формат day_code, чтобы использовать XSD / XPath yyyy-mm-dd, а затем просто написал два шаблона, сравнивающих значения in или out со значениями в первом block потомке:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="#all"
    version="3.0">

  <xsl:output indent="yes"/>

  <xsl:mode on-no-match="shallow-skip"/>

  <xsl:template match="Employee[day_code = 0]">
      <xsl:copy>
          <xsl:apply-templates/>
      </xsl:copy>
  </xsl:template>

  <xsl:template match="Employee[day_code = 0]/block[position() gt 1 and in > ../block[1]/in and out &lt;= ../block[1]/in]">
      <xsl:copy>
          <xsl:variable name="date" as="xs:date" select="xs:date(../day)"/>
          <xsl:variable name="new-date" as="xs:date" select="$date + xs:dayTimeDuration('P1D')"/>
          <in>
              <xsl:value-of select="dateTime($new-date, xs:time('00:01:00'))"/>
          </in>
          <out>
              <xsl:value-of select="dateTime($new-date, xs:time(replace(out, '([0-9]{2})([0-9]{2})', '$1:$2:00')))"/>
          </out>
          <xsl:apply-templates/>
      </xsl:copy>
  </xsl:template>

  <xsl:template match="Employee[day_code = 0]/block[position() gt 1 and in &lt;= ../block[1]/in]">
      <xsl:copy>
          <xsl:variable name="date" as="xs:date" select="xs:date(../day)"/>
          <xsl:variable name="new-date" as="xs:date" select="$date + xs:dayTimeDuration('P1D')"/>
          <in>
              <xsl:value-of select="dateTime($new-date, xs:time(replace(in, '([0-9]{2})([0-9]{2})', '$1:$2:00')))"/>
          </in>
          <out>
              <xsl:value-of select="dateTime($new-date, xs:time(replace(out, '([0-9]{2})([0-9]{2})', '$1:$2:00')))"/>
          </out>
          <xsl:apply-templates/>
      </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

https://xsltfiddle.liberty -development.net / 94rmq5Z дает результат

<Employee>
   <block>
      <in>2018-12-02T00:01:00</in>
      <out>2018-12-02T01:15:00</out>
   </block>
   <block>
      <in>2018-12-02T01:15:00</in>
      <out>2018-12-02T03:15:00</out>
   </block>
</Employee>

Обратите внимание, что должно произойти, если первый элемент блока имеет изменениенапример, имеет <in>0900</in>, но <out>0700</out>.

Примером является XSLT 3, но использование объявления xsl:mode может быть переписано в XSLT 2 с помощью

<xsl:template match="@* | node()">
  <xsl:apply-templates/>
</xsl:template>
...