首页 > 解决方案 > XSLT 按员工编号、年、月、日、小时、分钟、秒排序节点

问题描述

我有一个 XML 并希望:

例子 :

<?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 的排序工作,年/月等失败。

标签: xsltxslt-1.0xslt-2.0xslt-3.0

解决方案


我喜欢 Aljandro 的回答,但如果有人坚持使用更高版本的 XSLT 并将值真正视为yearmonthday-of-monthhoursminutesseconds的值,则可以使用以下类似的东西,

这种转换可能看起来有点复杂,但它会将 <bookingtime> 的子对象视为这些类型对象的值,如果遇到无效的组件值(例如Feb 30th, month :13, hour :),则会抛出错误: 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>

推荐阅读