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

时间:2022-01-31 07:10:57

Hope you guys are doing well.Thank you so much in advance.Your help will really appreciated.

希望你们做得很好。非常感谢你们。你们的帮助将非常感激。

Got into trouble to create the XSLT (v2.0) for below requirement.Not getting how to achieve it.

为以下要求创建XSLT(v2.0)时遇到了麻烦。没有得到如何实现它。

Requirement: Generate a unique Event Id based on consultative date and time type for each employees.

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

Example: For employee EMP12345 is on Annual leave for date 2015-03-31, Sick leave for period 2015-04-01 to 2015-04-03 and 2015-04-15 to 2015-04-16.

示例:对于员工,EMP12345的年假为2015-03-31,病假为2015-04-01至2015-04-03和2015-04-15至2015-04-16。

So there are 2 consecutive dated sick leave .So need to generate the two unique event id.

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

Please refer the below expected output.

请参考以下预期输出。

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>

Expected output:

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

Thanks,

Deepak

2 个解决方案

#1


0  

One possible way to do this, is to use xsl:for-each-group, and group starting by the Employee elements where the date is not one day after the previous one (i.e they are the start of a new group)

一种可能的方法是使用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'))]">

I am sure if you have a specific rule for generating the EventId, but one possible way would be as follows

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

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

You would then use current-group() to output all the rows in that particular group, with the same EventId. Try this XSLT:

然后,您将使用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>

When applied to you current XML, the following is output

当应用于您当前的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

Note, this does assume the Employee elements are sorted in Employee_id, Date, and time_type order.

注意,这确实假设Employee元素按Employee_id,Date和time_type顺序排序。

#2


0  

A big Thanks to @Tim for providing me the solution. I have just added the few criteria to full fill the requirement.

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

Below is the updated XSLT.

以下是更新的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>

#1


0  

One possible way to do this, is to use xsl:for-each-group, and group starting by the Employee elements where the date is not one day after the previous one (i.e they are the start of a new group)

一种可能的方法是使用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'))]">

I am sure if you have a specific rule for generating the EventId, but one possible way would be as follows

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

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

You would then use current-group() to output all the rows in that particular group, with the same EventId. Try this XSLT:

然后,您将使用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>

When applied to you current XML, the following is output

当应用于您当前的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

Note, this does assume the Employee elements are sorted in Employee_id, Date, and time_type order.

注意,这确实假设Employee元素按Employee_id,Date和time_type顺序排序。

#2


0  

A big Thanks to @Tim for providing me the solution. I have just added the few criteria to full fill the requirement.

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

Below is the updated XSLT.

以下是更新的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>