Узел сортировки XSLT по employeeNumber, году, месяцу, дню, часу, минутам, секундам - PullRequest
0 голосов
/ 22 марта 2019

У меня есть XML, и я хотел бы:

  • отсортировать по employeeNumber и для каждого времени бронирования по году, месяцу, возрастанию дня.

Пример:

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <entry>
        <employeeName>Bob the Builder</employeeName>
        <employeeNumber>00290035</employeeNumber>
        <requestCode>g</requestCode>
        <bookingtime>
            <year>2019</year>
            <month>3</month>
            <day>18</day>
            <hours>14</hours>
            <minutes>52</minutes>
            <seconds>0</seconds>
        </bookingtime>
    </entry>
    <entry>
        <employeeName>Bob the Builder</employeeName>
        <employeeNumber>00290035</employeeNumber>
        <requestCode>c</requestCode>
        <bookingtime>
            <year>2019</year>
            <month>3</month>
            <day>18</day>
            <hours>14</hours>
            <minutes>22</minutes>
            <seconds>0</seconds>
        </bookingtime>
    </entry>
    <entry>
        <employeeName>Mike Zeh</employeeName>
        <employeeNumber>00200060</employeeNumber>
        <requestCode>c</requestCode>
        <bookingtime>
            <year>2019</year>
            <month>3</month>
            <day>17</day>
            <hours>10</hours>
            <minutes>15</minutes>
            <seconds>0</seconds>
        </bookingtime>
    </entry>
</root>

Может кто-нибудь помочь мне сделать это правильно?Используемая версия XSLT может быть любой, никакой конкретной версии не требуется.

Я сделал небольшую скрипку (https://xsltfiddle.liberty -development.net / ej9EGce ), сортировка по employeeNumber работает, год /месяц и т. д. не проходит.

Ответы [ 2 ]

0 голосов
/ 24 марта 2019

Мне нравится ответ Альхандро, но в случае, если кто-то настаивает на использовании более высокой версии XSLT и действительно рассматривает значения как значения year , month , день месяца , часы , минуты и секунды , тогда можно использовать что-то подобное ниже,

Это преобразование может выглядеть немного сложнее, но оно обрабатывает дочерние элементы как значения этих типизированных объектов и выдает ошибку, если встречается недопустимое значение компонента, например Feb * 1019. * 30-е, месяц : 13, час : 25 или минута / секунда 61

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:xs="http://www.w3.org/2001/XMLSchema">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="root">
        <xsl:copy>
            <xsl:copy-of select="@*"/>
            <xsl:apply-templates select="entry">
                <xsl:sort select="employeeNumber" data-type="number"/>
                <xsl:sort select=
                "xs:dateTime(concat(
                                 string-join(
                                  (
                                      format-number(bookingtime/year, '0000'),
                                      format-number(bookingtime/month, '00'),
                                      format-number(bookingtime/day, '00')
                                  ), '-'
                                             ),
                                 'T',
                                 string-join(
                                  (
                                      format-number(bookingtime/hours, '00'),
                                      format-number(bookingtime/minutes, '00'),
                                      format-number(bookingtime/seconds, '00')
                                  ), ':'
                                            )
                                   )
                             )"/>
            </xsl:apply-templates>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

Когда это преобразование применяется к предоставленному исходному XML-документу :

<root>
    <entry>
        <employeeName>Bob the Builder</employeeName>
        <employeeNumber>00290035</employeeNumber>
        <requestCode>g</requestCode>
        <bookingtime>
            <year>2019</year>
            <month>3</month>
            <day>18</day>
            <hours>14</hours>
            <minutes>52</minutes>
            <seconds>0</seconds>
        </bookingtime>
    </entry>
    <entry>
        <employeeName>Bob the Builder</employeeName>
        <employeeNumber>00290035</employeeNumber>
        <requestCode>c</requestCode>
        <bookingtime>
            <year>2018</year>
            <month>3</month>
            <day>18</day>
            <hours>14</hours>
            <minutes>22</minutes>
            <seconds>0</seconds>
        </bookingtime>
    </entry>
    <entry>
        <employeeName>Mike Zeh</employeeName>
        <employeeNumber>00200060</employeeNumber>
        <requestCode>c</requestCode>
        <bookingtime>
            <year>2019</year>
            <month>3</month>
            <day>17</day>
            <hours>10</hours>
            <minutes>15</minutes>
            <seconds>0</seconds>
        </bookingtime>
    </entry>
</root>

желаемый, правильный результат выдается :

<root>
   <entry>
        <employeeName>Mike Zeh</employeeName>
        <employeeNumber>00200060</employeeNumber>
        <requestCode>c</requestCode>
        <bookingtime>
            <year>2019</year>
            <month>3</month>
            <day>17</day>
            <hours>10</hours>
            <minutes>15</minutes>
            <seconds>0</seconds>
        </bookingtime>
    </entry>
   <entry>
        <employeeName>Bob the Builder</employeeName>
        <employeeNumber>00290035</employeeNumber>
        <requestCode>c</requestCode>
        <bookingtime>
            <year>2018</year>
            <month>3</month>
            <day>18</day>
            <hours>14</hours>
            <minutes>22</minutes>
            <seconds>0</seconds>
        </bookingtime>
    </entry>
   <entry>
        <employeeName>Bob the Builder</employeeName>
        <employeeNumber>00290035</employeeNumber>
        <requestCode>g</requestCode>
        <bookingtime>
            <year>2019</year>
            <month>3</month>
            <day>18</day>
            <hours>14</hours>
            <minutes>52</minutes>
            <seconds>0</seconds>
        </bookingtime>
    </entry>
</root>
0 голосов
/ 22 марта 2019

Эта таблица стилей

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="root">
        <xsl:copy>
            <xsl:copy-of select="@*"/>
            <xsl:apply-templates select="entry">
                <xsl:sort select="employeeNumber" data-type="number"/>
                <xsl:sort select="bookingtime/year" data-type="number"/>
                <xsl:sort select="bookingtime/month" data-type="number"/>
                <xsl:sort select="bookingtime/day" data-type="number"/>
                <xsl:sort select="bookingtime/hours" data-type="number"/>
                <xsl:sort select="bookingtime/minutes" data-type="number"/>
                <xsl:sort select="bookingtime/seconds" data-type="number"/>
            </xsl:apply-templates>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

С вашим вводом

<root>
    <entry>
        <employeeName>Bob the Builder</employeeName>
        <employeeNumber>00290035</employeeNumber>
        <requestCode>g</requestCode>
        <bookingtime>
            <year>2019</year>
            <month>3</month>
            <day>18</day>
            <hours>14</hours>
            <minutes>52</minutes>
            <seconds>0</seconds>
        </bookingtime>
    </entry>
    <entry>
        <employeeName>Bob the Builder</employeeName>
        <employeeNumber>00290035</employeeNumber>
        <requestCode>c</requestCode>
        <bookingtime>
            <year>2018</year>
            <month>3</month>
            <day>18</day>
            <hours>14</hours>
            <minutes>22</minutes>
            <seconds>0</seconds>
        </bookingtime>
    </entry>
    <entry>
        <employeeName>Mike Zeh</employeeName>
        <employeeNumber>00200060</employeeNumber>
        <requestCode>c</requestCode>
        <bookingtime>
            <year>2019</year>
            <month>3</month>
            <day>17</day>
            <hours>10</hours>
            <minutes>15</minutes>
            <seconds>0</seconds>
        </bookingtime>
    </entry>
</root>

Вывод:

<root>
   <entry>
      <employeeName>Mike Zeh</employeeName>
      <employeeNumber>00200060</employeeNumber>
      <requestCode>c</requestCode>
      <bookingtime>
         <year>2019</year>
         <month>3</month>
         <day>17</day>
         <hours>10</hours>
         <minutes>15</minutes>
         <seconds>0</seconds>
      </bookingtime>
   </entry>
   <entry>
      <employeeName>Bob the Builder</employeeName>
      <employeeNumber>00290035</employeeNumber>
      <requestCode>c</requestCode>
      <bookingtime>
         <year>2018</year>
         <month>3</month>
         <day>18</day>
         <hours>14</hours>
         <minutes>22</minutes>
         <seconds>0</seconds>
      </bookingtime>
   </entry>
   <entry>
      <employeeName>Bob the Builder</employeeName>
      <employeeNumber>00290035</employeeNumber>
      <requestCode>g</requestCode>
      <bookingtime>
         <year>2019</year>
         <month>3</month>
         <day>18</day>
         <hours>14</hours>
         <minutes>52</minutes>
         <seconds>0</seconds>
      </bookingtime>
   </entry>
</root>

Обратите внимание: если вы сортируете entry элементов, вы можетеиспользуйте любой относительный путь с каждым entry в качестве контекста для атрибута select инструкции xsl:sort.Это сортировка (выводить каждые entry), отличная от группировки (выводить дискретные данные entry и вычислять некоторую агрегацию)

...