如何在 XSLT 中对连续日期进行分组? [英] How to group consecutive dates in XSLT?

查看:29
本文介绍了如何在 XSLT 中对连续日期进行分组?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 xml 文件(下面的示例),我想根据连续的 Time_Off_Date 对这个 xml 进行分组.

<块引用>

<进入><Employee_ID>101</Employee_ID><Time_Off_Details><Time_Off_Date>2017-12-01</Time_Off_Date></Time_Off_Details><Time_Off_Details><Time_Off_Date>2017-12-02</Time_Off_Date></Time_Off_Details><Time_Off_Details><Time_Off_Date>2017-12-04</Time_Off_Date></Time_Off_Details><Time_Off_Details><Time_Off_Date>2017-12-05</Time_Off_Date></Time_Off_Details></条目><进入><Employee_ID>102</Employee_ID><Time_Off_Details><Time_Off_Date>2017-12-10</Time_Off_Date></Time_Off_Details><Time_Off_Details><Time_Off_Date>2017-12-13</Time_Off_Date></Time_Off_Details><Time_Off_Details><Time_Off_Date>2017-12-14</Time_Off_Date></Time_Off_Details></条目></Root>

最终输出应如下所示(CSV 格式).

<块引用>

员工 ID 休假开始 休假结束101 12/1/2017 12/2/2017101 12/4/2017 12/5/2017102 12/10/2017 12/10/2017102 12/13/2017 12/14/2017

有没有办法使用 XSLT 2.0 而不使用递归函数来实现这一点?我是 XSLT 的新手,因此不胜感激.

解决方案

如果逻辑是输入 XML 只保留单独的休息日,并且您想将这些单独的几天(恰好是连续的)分组,那么您可以使用 xsl:for-each-group 选择 Time_Off_Details 并将 group-starting-with 设置为 Time_Off_Date 与前一个元素不连续.

试试这个 XSLT

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"xmlns:xs="http://www.w3.org/2001/XMLSchema"版本=2.0"><xsl:output method="text"/><xsl:strip-space elements="*"/><xsl:template match="条目"><xsl:for-each-group select="Time_Off_Details"group-starting-with="*[not(xs:date(Time_Off_Date) = xs:date(preceding-sibling::*[1]/Time_Off_Date) + xs:dayTimeDuration('P1D'))]"><xsl:value-of select="../Employee_ID"/><xsl:text>,</xsl:text><xsl:value-of select="Time_Off_Date"/><xsl:text>,</xsl:text><xsl:value-of select="current-group()[last()]/Time_Off_Date"/><xsl:text>&#10;</xsl:text></xsl:for-each-group></xsl:模板></xsl:stylesheet>

I have an xml file (sample below) and I want to group this xml based on consecutive Time_Off_Date.

<Root>
  <Entry>
    <Employee_ID>101</Employee_ID>
    <Time_Off_Details>
      <Time_Off_Date>2017-12-01</Time_Off_Date>
    </Time_Off_Details>
    <Time_Off_Details>
      <Time_Off_Date>2017-12-02</Time_Off_Date>
    </Time_Off_Details>
    <Time_Off_Details>
      <Time_Off_Date>2017-12-04</Time_Off_Date>
    </Time_Off_Details>
    <Time_Off_Details>
      <Time_Off_Date>2017-12-05</Time_Off_Date>
    </Time_Off_Details> 
  </Entry>
  <Entry>
    <Employee_ID>102</Employee_ID>
    <Time_Off_Details>
      <Time_Off_Date>2017-12-10</Time_Off_Date>
    </Time_Off_Details>
    <Time_Off_Details>
      <Time_Off_Date>2017-12-13</Time_Off_Date>
    </Time_Off_Details>
    <Time_Off_Details>
      <Time_Off_Date>2017-12-14</Time_Off_Date>
    </Time_Off_Details>
  </Entry>
</Root>

The final output should look like this (in CSV format).

Employee ID   Time Off Start  Time Off End
101           12/1/2017       12/2/2017
101           12/4/2017       12/5/2017
102           12/10/2017      12/10/2017
102           12/13/2017      12/14/2017

Is there a way to achieve this using XSLT 2.0 and without using recursive functions?? I am new to XSLT so any advice is appreciated.

解决方案

If the logic is that the input XML only holds individual days off and you want to group these individual days where they happen to be consecutive, then you can use xsl:for-each-group to select the Time_Off_Details with the group-starting-with set to the elements where the Time_Off_Date is not consecutive with the previous element.

Try this XSLT

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
                xmlns:xs="http://www.w3.org/2001/XMLSchema"
                version="2.0">

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

  <xsl:template match="Entry">
    <xsl:for-each-group select="Time_Off_Details" 
                        group-starting-with="*[not(xs:date(Time_Off_Date) = xs:date(preceding-sibling::*[1]/Time_Off_Date) + xs:dayTimeDuration('P1D'))]">
        <xsl:value-of select="../Employee_ID" />
        <xsl:text>,</xsl:text>
        <xsl:value-of select="Time_Off_Date" />
        <xsl:text>,</xsl:text>
        <xsl:value-of select="current-group()[last()]/Time_Off_Date" />
        <xsl:text>&#10;</xsl:text>
    </xsl:for-each-group>
  </xsl:template>
</xsl:stylesheet>

这篇关于如何在 XSLT 中对连续日期进行分组?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆