我要求将相同类型的相应日期时间打印成一行,总时间为每次关闭行的单位总和,以及具有最早时间的最开始日期的开始日期和行结束日期是基于下面的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
答案 0 :(得分:0)
类似的问题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)), ',')), ' ')
使用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()) || ' '"/>
</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()), ' ')"/>
而不是<xsl:value-of select="mf:line(current-group()) || ' '"/>
。