Создание уникального идентификатора события на основе последовательного элемента даты и типа времени в xslt

Надеюсь, у вас все хорошо. Заранее большое спасибо. Ваша помощь будет очень признательна.

Возникли проблемы с созданием XSLT (v2.0) для нижеприведенного требования. Не понимаю, как этого добиться.

Требование: создавайте уникальный идентификатор события на основе рекомендуемой даты и времени для каждого сотрудника.

Пример: сотрудник EMP12345 находится в ежегодном отпуске на дату 31 марта 2015 г., в отпуске по болезни за период с 1 апреля 2015 г. по 03 апреля 2015 г. и 4 апреля 2015 г. -15 до 2015-04-16.

Таким образом, есть 2 отпуска по болезни с датой подряд. Поэтому необходимо создать два уникальных идентификатора события.

Пожалуйста, обратитесь к ожидаемому результату ниже.

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

Спасибо,

Дипак


person Deepak singh    schedule 17.04.2015    source источник


Ответы (2)


Один из возможных способов сделать это - использовать 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_id, Date и time_type.

person Tim C    schedule 17.04.2015
comment
Тим, спасибо, попробую. Предположим, что если работники брали больничные с пятницы по вторник. Отпуск последовательный, но дата не будет последовательной, например 2015-04-17,2015-04-17. Для этого примера дата будет 2015-04-17,2015-04-20,2015-04-21. Потому что суббота и воскресенье не будут учитываться. Возможно ли включить эту логику в приведенный выше xslt. Если разница в датах, должна быть разница в два дня, и первая дата должна быть в пятницу, а следующая дата должна быть в понедельник, у этого также должен быть уникальный идентификатор события. Спасибо, Тим. - person Deepak singh; 18.04.2015
comment
Спасибо, я изменил файл xslt. в состоянии применить логику для вышеуказанного требования. - person Deepak singh; 18.04.2015

Большое спасибо @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>

person Deepak singh    schedule 18.04.2015