【问题标题】:Generating unique event ID based on consecutive dated element and time type in xslt根据xslt中的连续日期元素和时间类型生成唯一事件ID
【发布时间】:2015-04-17 15:49:03
【问题描述】:

希望你们一切顺利。在此先感谢你们。非常感谢你们的帮助。

为以下要求创建 XSLT (v2.0) 时遇到麻烦。不知道如何实现它。

要求: 根据每位员工的咨询日期和时间类型生成唯一的事件 ID

示例: 员工 EMP12345 于 2015 年 3 月 31 日休年假,于 2015 年 4 月 1 日至 2015 年 4 月 3 日休病假,以及2015 年 4 月 15 日至 2015 年 4 月 16 日。

所以有2个连续的日期病假。所以需要生成两个唯一的事件ID。

请参考以下预期输出。

XML

<?xml version='1.0' encoding='UTF-8'?>
<Data>
<Employee>
    <Employee_ID>EMP12345</Employee_ID>
    <Time_type>Annual</Time_type>
    <Date>2015-03-31</Date>
    <Hours>6</Hours>
</Employee>
<Employee>
    <Employee_ID>EMP12345</Employee_ID>
    <Time_type>Sick</Time_type>
    <Date>2015-04-01</Date>
    <Hours>6</Hours>
</Employee>
<Employee>
    <Employee_ID>EMP12345</Employee_ID>
    <Time_type>Sick</Time_type>
    <Date>2015-04-02</Date>
    <Hours>6</Hours>
</Employee>
<Employee>
    <Employee_ID>EMP12345</Employee_ID>
    <Time_type>Sick</Time_type>
    <Date>2015-04-03</Date>
    <Hours>6</Hours>
</Employee>
<Employee>
    <Employee_ID>EMP12345</Employee_ID>
    <Time_type>Sick</Time_type>
    <Date>2015-04-15</Date>
    <Hours>6</Hours>
</Employee>
<Employee>
    <Employee_ID>EMP12345</Employee_ID>
    <Time_type>Sick</Time_type>
    <Date>2015-04-16</Date>
    <Hours>6</Hours>
</Employee>
<Employee>
    <Employee_ID>EMP12346</Employee_ID>
    <Time_type>Sick</Time_type>
    <Date>2015-04-01</Date>
    <Hours>6</Hours>
</Employee>
<Employee>
    <Employee_ID>EMP12346</Employee_ID>
    <Time_type>Sick</Time_type>
    <Date>2015-04-02</Date>
    <Hours>6</Hours>
</Employee>
</Data>

预期输出:

Employee ID,Time Type,Date,Hours,Event ID
EMP12345,Annual,2015-03-31,6,
EMP12345,Sick,2015-04-01,6,12344EMP12345
EMP12345,Sick,2015-04-02,6,12344EMP12345
EMP12345,Sick,2015-04-03,6,12344EMP12345
EMP12345,Sick,2015-04-15,6,22344EMP12345
EMP12345,Sick,2015-04-16,6,22344EMP12345
EMP12346,Sick,2015-04-01,6,11111EMP12346
EMP12346,Sick,2015-04-02,6,11111EMP12346

谢谢,

迪帕克

【问题讨论】:

    标签: xml xslt xslt-2.0 xslt-grouping


    【解决方案1】:

    一种可能的方法是使用xsl:for-each-group,并从Employee 元素开始分组,其中日期不是前一天之后的一天(即它们是新组的开始)

      <xsl:for-each-group select="Employee" group-starting-with="Employee[not(
           Employee_ID = preceding-sibling::Employee[1]/Employee_ID 
           and Time_type = preceding-sibling::Employee[1]/Time_type 
           and xs:date(Date) = xs:date(preceding-sibling::Employee[1]/Date) + xs:dayTimeDuration('P1D'))]">
    

    我确定您是否有生成 EventId 的特定规则,但一种可能的方法如下

    <xsl:variable name="EventId" select="concat(Employee_ID, '-', position())" />
    

    然后您将使用current-group() 输出该特定组中具有相同EventId 的所有行。试试这个 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:template match="Data">
          <xsl:for-each-group select="Employee" group-starting-with="Employee[not(
            Employee_ID = preceding-sibling::Employee[1]/Employee_ID 
            and Time_type = preceding-sibling::Employee[1]/Time_type 
            and xs:date(Date) = xs:date(preceding-sibling::Employee[1]/Date) + xs:dayTimeDuration('P1D'))]">
              <xsl:variable name="EventId" select="concat(Employee_ID, '-', position())" />
              <xsl:for-each select="current-group()">
                  <xsl:value-of select="Employee_ID" />
                  <xsl:text>,</xsl:text>
                  <xsl:value-of select="Time_type" />
                  <xsl:text>,</xsl:text>
                  <xsl:value-of select="Date" />
                  <xsl:text>,</xsl:text>
                  <xsl:value-of select="Hours" />
                  <xsl:text>,</xsl:text>
                  <xsl:value-of select="$EventId" />
                  <xsl:text>&#10;</xsl:text>
              </xsl:for-each>
          </xsl:for-each-group>
        </xsl:template>
    
        <xsl:template match="@*|node()">
            <xsl:copy>
                <xsl:apply-templates select="@*|node()"/>
            </xsl:copy>
        </xsl:template>
    </xsl:stylesheet>
    

    当应用到你当前的 XML 时,以下是输出

    EMP12345,Annual,2015-03-31,6,EMP12345-1
    EMP12345,Sick,2015-04-01,6,EMP12345-2
    EMP12345,Sick,2015-04-02,6,EMP12345-2
    EMP12345,Sick,2015-04-03,6,EMP12345-2
    EMP12345,Sick,2015-04-15,6,EMP12345-3
    EMP12345,Sick,2015-04-16,6,EMP12345-3
    EMP12346,Sick,2015-04-01,6,EMP12346-4
    EMP12346,Sick,2015-04-02,6,EMP12346-4
    

    注意,这确实假设Employee 元素按Employee_idDatetime_type 顺序排序。

    【讨论】:

    • 谢谢蒂姆,我会试试的。假设员工从周五到周二开始请病假。休假是连续的,但日期不会像 2015-04-17,2015-04-17 那样连续。对于此示例,日期将是 2015-04-17,2015-04-20,2015-04-21。因为星期六和星期日不会被计算在内。这是否可以将这个逻辑合并到上面的 xslt.如果日期差应该有两天差,第一个日期应该是星期五,下一个日期应该是星期一,这也应该有唯一的事件 ID。谢谢蒂姆。
    • 感谢我修改了 xslt。能够应用上述要求的逻辑。
    【解决方案2】:

    非常感谢@Tim 为我提供了解决方案。 我刚刚添加了几个标准来完全满足要求。

    以下是更新后的 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:template match="Data">
       <xsl:for-each-group select="Employee" group-starting-with="Employee[not(
            Employee_ID = preceding-sibling::Employee[1]/Employee_ID 
            and Time_type = preceding-sibling::Employee[1]/Time_type 
            and ((xs:date(Date) =  xs:date(preceding-sibling::Employee[1]/Date) + xs:dayTimeDuration('P1D')) 
    		or ((xs:date(Date) =  xs:date(preceding-sibling::Employee[1]/Date) + xs:dayTimeDuration('P3D')) and (format-date(xs:date(Date),'[F]')='Monday') and (format-date((xs:date(preceding-sibling::Employee[1]/Date)),'[F]')='Friday')  ) ))]">
              <xsl:variable name="EventId" select="concat(Employee_ID, '-', position())" />
    		<xsl:for-each select="current-group()">
                  <xsl:value-of select="Employee_ID" />
                  <xsl:text>,</xsl:text>
                  <xsl:value-of select="Time_type" />
                  <xsl:text>,</xsl:text>
                  <xsl:value-of select="Date" />
                  <xsl:text>,</xsl:text>
                  <xsl:value-of select="Hours" />
                  <xsl:text>,</xsl:text>
                  <xsl:value-of select="$EventId" />
                  
                  <xsl:text>&#10;</xsl:text>
              </xsl:for-each>
          </xsl:for-each-group>
        </xsl:template>
    
        <xsl:template match="@*|node()">
            <xsl:copy>
                <xsl:apply-templates select="@*|node()"/>
            </xsl:copy>
        </xsl:template>
    </xsl:stylesheet>

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多