如何用XSLT的for-each-group按Code合并连续日期休假记录
问题:合并同一Code下连续日期的休假记录
我需要在XSL中实现嵌套分组,按Time_Data/Time_Off/Code分组,将同一Code下日期连续的休假记录合并为一行;非连续的记录(包括单日或多段不连续的连续日期)则单独成行。示例中有两个Code各有连续记录(一个3天、一个4天),还有两个无连续日期的Code记录。
输入XML
<?xml version="1.0" encoding="utf-8"?> <Output xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <Record> <Employee_ID>123456</Employee_ID> <Payroll_ID>1111</Payroll_ID> <Time_Data> <Date>2023-11-04</Date> <Day>Saturday</Day> <Time_Off> <Code>DL</Code> <Date>2023-11-04</Date> <Quantity>7</Quantity> <Unit>HOURS</Unit> </Time_Off> <Time_Off> <Code>RJ</Code> <Date>2023-11-04</Date> <Quantity>1</Quantity> <Unit>HOURS</Unit> </Time_Off> </Time_Data> <Time_Data> <Date>2023-11-05</Date> <Day>Sunday</Day> <Time_Off> <Code>DL</Code> <Date>2023-11-05</Date> <Quantity>7</Quantity> <Unit>HOURS</Unit> </Time_Off> <Time_Off> <Code>RJ</Code> <Date>2023-11-05</Date> <Quantity>1</Quantity> <Unit>HOURS</Unit> </Time_Off> </Time_Data> <Time_Data> <Date>2023-11-06</Date> <Day>Monday</Day> <Time_Off> <Code>DL</Code> <Date>2023-11-06</Date> <Quantity>7</Quantity> <Unit>HOURS</Unit> </Time_Off> <Time_Off> <Code>RJ</Code> <Date>2023-11-06</Date> <Quantity>1</Quantity> <Unit>HOURS</Unit> </Time_Off> </Time_Data> <Time_Data> <Date>2023-11-07</Date> <Day>Tuesday</Day> <Time_Off> <Code>RJ</Code> <Date>2023-11-07</Date> <Quantity>1</Quantity> <Unit>HOURS</Unit> </Time_Off> </Time_Data> <Time_Data> <Date>2023-11-15</Date> <Day>Monday</Day> <Time_Off> <Code>DL</Code> <Date>2023-11-15</Date> <Quantity>7</Quantity> <Unit>HOURS</Unit> </Time_Off> <Time_Off> <Code>RJ</Code> <Date>2023-11-15</Date> <Quantity>1</Quantity> <Unit>HOURS</Unit> </Time_Off> </Time_Data> </Record> </Output>
当前使用的XSL转换代码
<xsl:for-each select="Output/Record"> <xsl:for-each-group select="Time_Data/Time_Off" group-by="concat(Code, '|', Date)"> <xsl:for-each-group select="current-group()" group-starting-with="*[not(xs:date(Date) = xs:date(preceding-sibling::*[1]/Date) + xs:dayTimeDuration('P1D'))]"> <xsl:value-of select="format-number(../../Payroll_ID, '00000000')"/> <xsl:value-of select="' '"/> <xsl:value-of select="format-date(Date, '[D01][M01]')"/> <xsl:value-of select="format-date(current-group()[last()]/Date, '[D01][M01]')"/> <xsl:value-of select="' '"/> <xsl:value-of select="format-number(sum(current-group()/Quantity) * 100, '0000')"/> <xsl:value-of select="Code"/> <xsl:value-of select="'TT'"/> <xsl:value-of select="$linefeed"/> </xsl:for-each-group> </xsl:for-each-group> </xsl:for-each>
当前输出结果
00001111 04110411 0700DLTT 00001111 04110411 0100RJTT 00001111 05110511 0700DLTT 00001111 05110511 0100RJTT 00001111 06110611 0700DLTT 00001111 06110611 0100RJTT 00001111 07110711 0100RJTT 00001111 15111511 0700DLTT 00001111 15111511 0100RJTT
期望输出结果
00001111 04110611 2100DLTT 00001111 04110711 0400RJTT 00001111 15111511 0700DLTT 00001111 15111511 0100RJTT
遇到的问题
我尝试过嵌套多个按Code分组的for-each-group,但无法得到正确的行数,循环迭代次数过多,不清楚正确的分组方式。
有效解决方案
感谢michael.hor257k提供的解答,以下是可行的XSL代码:
<xsl:for-each select="Output/Record"> <xsl:for-each-group select="Time_Data/Time_Off" group-by="Code"> <xsl:for-each-group select="current-group()" group-adjacent="xs:date(Date) - position()*xs:dayTimeDuration('P1D')"> <xsl:value-of select="format-number(../../Payroll_ID, '00000000')"/> <xsl:value-of select="' '"/> <xsl:value-of select="format-date(Date, '[D01][M01]')"/> <xsl:value-of select="format-date(current-group()[last()]/Date, '[D01][M01]')"/> <xsl:value-of select="' '"/> <xsl:value-of select="format-number(sum(current-group()/Quantity) * 100, '0000')"/> <xsl:value-of select="current-group()[1]/Code"/> <xsl:value-of select="'TT'"/> <xsl:value-of select="$linefeed"/> </xsl:for-each-group> </xsl:for-each-group> </xsl:for-each>
内容的提问来源于stack exchange,提问作者schwiz23
相关产品推荐
相关产品推荐

