根据 xslt 中的连续日期元素和时间类型生成唯一事件 ID

Generating unique event ID based on consecutive dated element and time type in xslt

希望你们 well.Thank 非常感谢你们 advance.Your 的帮助。

在为以下内容创建 XSLT (v2.0) 时遇到了麻烦requirement.Not 了解如何实现它。

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

示例: 对于员工 EMP12345 正在休年假,日期为 2015-03-31,病假时间为 2015-04- 01 至 2015-04-03 和 2015-04-15 至 2015-04-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

谢谢,

迪帕克

一种可能的方法是使用 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 顺序排序。

非常感谢@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>