xslt 中相同类型的连续日期休假总数

Total of consecutively dated time offs of the same type in xslt

我需要将相同类型的相应日期的休假打印到一行中,总休假时间是每个休假行的单位总和,开始日期是最早休假行的开始日期结束日期是基于下方 XML 的最晚休假行开始日期。

--XML--

<?xml version='1.0' encoding='UTF-8'?>
<Data>
    <Worker>
        <Worker_ID>12</Worker_ID>
        <Time_Off>
            <Type>Compassionate Leave</Type>
            <Date>2018-02-09-08:00</Date>
            <Units>1</Units>
        </Time_Off>
        <Time_Off>
            <Type>Compassionate Leave</Type>
            <Date>2018-02-08-08:00</Date>
            <Units>1</Units>
        </Time_Off>
        <Time_Off>
            <Type>Compassionate Leave</Type>
            <Date>2018-02-02-08:00</Date>
            <Units>1</Units>
        </Time_Off>
        <Time_Off>
            <Type>Compassionate Leave</Type>
            <Date>2018-02-01-08:00</Date>
            <Units>1</Units>
        </Time_Off>
        <Time_Off>
            <Type>Statutory Holiday</Type>
            <Date>2018-02-07-08:00</Date>
            <Units>1</Units>
        </Time_Off>
        <Time_Off>
            <Type>Statutory Holiday</Type>
            <Date>2018-02-06-08:00</Date>
            <Units>1</Units>
        </Time_Off>
    </Worker>
    <Worker>
        <Worker_ID>09</Worker_ID>
        <Time_Off>
            <Type>Sick Leave</Type>
            <Date>2018-02-10-08:00</Date>
            <Units>1</Units>
        </Time_Off>
    </Worker>
    <Worker>
        <Worker_ID>13</Worker_ID>
        <Time_Off>
            <Type>Vacation</Type>
            <Date>2018-02-11-08:00</Date>
            <Units>1</Units>
        </Time_Off>
        <Time_Off>
            <Type>Vacation</Type>
            <Date>2018-01-10-08:00</Date>
            <Units>1</Units>
        </Time_Off>
    </Worker>
</Data>

-期望的输出--

    EmployeeID,TimeOff Type,TimeOff Start Date,TimeOff End Date,Total Units 
    12,Compassionate Leave,2018-02-08,2018-02-09,2
    12,Compassionate Leave,2018-02-01,2018-02-02,2
    12,Statutory Holiday,2018-02-06,2018-02-07,2
    09,Sick Leave,2018-02-10,2018-02-10,1
    13,Vacation,2018-02-11,2018-02-11,1
    13,Vacation,2018-01-10,2018-01-10,1

一个类似的问题 How to group consecutive dates in XSLT? 有一些解决它的建议,无论是使用 XSLT 还是使用 XQuery。

https://xqueryfiddle.liberty-development.net/pPgCcoj/1 是尝试使用 XQuery 3 中的 window 子句来解决您的问题:

declare function local:date($input as xs:string) as xs:date {
    xs:date(substring($input, 1, 10))
};


string-join((
    'EmployeeID,TimeOff Type,TimeOff Start Date,TimeOff End Date,Total Units',
for $worker in Data/Worker
for $time-off in $worker/Time_Off
group by $type := data($time-off/Type)
return
    let $times := for $time in $time-off
                  order by local:date($time/Date)
                  return $time
    return 
        for tumbling window $line in $times
        start $s when true()
        end $e next $n when empty($n) or local:date($n/Date) - local:date($e/Date) ne xs:dayTimeDuration('P1D')
        return string-join(
            ($worker/Worker_ID, $type, local:date($s/Date), local:date($e/Date), sum($line/Units)), ',')), '&#10;')

您可以使用 XSLT

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

  <xsl:output method="text"/>
  <xsl:strip-space elements="*"/>

  <xsl:function name="mf:date" as="xs:date">
      <xsl:param name="input" as="xs:string"/>
      <xsl:sequence select="xs:date(substring($input, 1, 10))"/>
  </xsl:function>

  <xsl:function name="mf:line" as="xs:string">
      <xsl:param name="group" as="element(Time_Off)*"/>
      <xsl:value-of 
        select="$group[1]/../Worker_ID, 
                $group[1]/Type, 
                mf:date($group[1]/Date),
                mf:date($group[last()]/Date),
                sum($group/Units)"
                separator=","/>      
  </xsl:function>

  <xsl:template match="Worker">
      <xsl:for-each-group select="Time_Off" group-by="Type">
          <xsl:variable name="sorted-times" as="element(Time_Off)*">
              <xsl:perform-sort select="current-group()">
                  <xsl:sort select="mf:date(Date)"/>
              </xsl:perform-sort>
          </xsl:variable>
          <xsl:for-each-group select="$sorted-times" group-by="mf:date(Date) - xs:dayTimeDuration('P1D') * position()">
              <xsl:value-of select="mf:line(current-group()) || '&#10;'"/>
          </xsl:for-each-group>
      </xsl:for-each-group>
  </xsl:template>

</xsl:stylesheet>

在线 https://xsltfiddle.liberty-development.net/pPgCcov/1。对于 XSLT 2 处理器,您需要使用 <xsl:value-of select="concat(mf:line(current-group()), '&#10;')"/> 而不是 <xsl:value-of select="mf:line(current-group()) || '&#10;'"/>