【问题标题】:XSLT - Match and group timesXSLT - 比赛和分组时间
【发布时间】:2019-02-28 22:13:53
【问题描述】:

我正在尝试根据下面的 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>`

我正在考虑使用前面的兄弟函数检查两个块。检查第一个块的进入时间是否小于第二个块的退出时间条目,第二个条件是检查立即块的进入时间是否小于退出时间,但这不是很好。

非常感谢任何帮助!

【问题讨论】:

  • 日期和/或时间格式分别是 XSLT/XPath 2 和更高版本的 XSD 日期和时间格式,还是与示例数据中的一样糟糕?至于时间值,如何决定是否0900 是在午夜之前还是之后?
  • 它只是示例数据,都需要是 XSLT/xpath 2 格式。对于你的第二个问题......这就是我遇到的问题。这就是为什么我正在考虑使用“preceding-sibling”来比较两个块中的条目,以确定是早上还是午夜之后。
  • 所以我们可以假设第一个 block 孩子总是在午夜之前,我们可以确定午夜之后的第一个孩子是选择第一个后续兄弟block,其时间小于或等于第一个block?
  • 是的,你的假设是正确的。

标签: xml xslt xsd xslt-2.0 transformation


【解决方案1】:

我“修复”了 day_code 的格式以使用 XSD/XPath yyyy-mm-dd,然后简单地编写了两个模板,将 inout 的值与第一个 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>

请注意,如果第一个块元素确实发生了变化,例如有&lt;in&gt;0900&lt;/in&gt; 但有&lt;out&gt;0700&lt;/out&gt;

示例是 XSLT 3,但 xsl:mode 声明的使用可以通过使用在 XSLT 2 中重写

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

【讨论】:

    猜你喜欢
    • 2019-04-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-24
    • 2017-09-18
    • 2017-05-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多