如何解决使用XSLT 2.0按日期降序对XML节点进行排序
我有一组节点,这些节点显示来自两个不同系统(不同节点)的工人报酬以及生效日期。无论这些值来自先前系统还是当前系统,我都需要按升/降顺序对其进行排序。
我尝试在for-each中使用sort函数,但是我收到一个错误,即排序时最多可以传递1个节点。
<?xml version="1.0" encoding="UTF-8"?>
<Workers xmlns:ch="test/Compensation_History">
<ch:Worker_Entry>
<ch:Employee_ID>12345</ch:Employee_ID>
<ch:Compensation_History_PrevIoUs_System>
<ch:Amount>100000</ch:Amount>
<ch:Effective_Date>2018-01-01-07:00</ch:Effective_Date>
</ch:Compensation_History_PrevIoUs_System>
<ch:Compensation_History_PrevIoUs_System>
<ch:Amount>95000</ch:Amount>
<ch:Effective_Date>2017-01-01-07:00</ch:Effective_Date>
</ch:Compensation_History_PrevIoUs_System>
<ch:Compensation_History_PrevIoUs_System>
<ch:Amount>90000</ch:Amount>
<ch:Effective_Date>2016-01-01-07:00</ch:Effective_Date>
</ch:Compensation_History_PrevIoUs_System>
<ch:Compensation_History_Current_System>
<ch:Amount>105000</ch:Amount>
<ch:Effective_Date>2019-01-01-07:00</ch:Effective_Date>
</ch:Compensation_History_Current_System>
<ch:Compensation_History_Current_System>
<ch:Amount>110000</ch:Amount>
<ch:Effective_Date>2020-01-01-07:00</ch:Effective_Date>
</ch:Compensation_History_Current_System>
</ch:Worker_Entry>
</Workers>
预期输出:
<?xml version="1.0" encoding="UTF-8"?>
<Workers xmlns:ch="test/Compensation_History">
<ch:Worker_Entry>
<ch:Employee_ID>12345</ch:Employee_ID>
<ch:Compensation_History_Current_System>
<ch:Amount>110000</ch:Amount>
<ch:Effective_Date>2020-01-01-07:00</ch:Effective_Date>
</ch:Compensation_History_Current_System>
<ch:Compensation_History_Current_System>
<ch:Amount>105000</ch:Amount>
<ch:Effective_Date>2019-01-01-07:00</ch:Effective_Date>
</ch:Compensation_History_Current_System>
<ch:Compensation_History_PrevIoUs_System>
<ch:Amount>100000</ch:Amount>
<ch:Effective_Date>2018-01-01-07:00</ch:Effective_Date>
</ch:Compensation_History_PrevIoUs_System>
<ch:Compensation_History_PrevIoUs_System>
<ch:Amount>95000</ch:Amount>
<ch:Effective_Date>2017-01-01-07:00</ch:Effective_Date>
</ch:Compensation_History_PrevIoUs_System>
<ch:Compensation_History_PrevIoUs_System>
<ch:Amount>90000</ch:Amount>
<ch:Effective_Date>2016-01-01-07:00</ch:Effective_Date>
</ch:Compensation_History_PrevIoUs_System>
</ch:Worker_Entry>
</Workers>
下面是我尝试过的代码:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:ch="test/Compensation_History" exclude-result-prefixes="xs"
version="2.0">
<xsl:template match="/">
<Workers>
<xsl:for-each-group select="ch:Workers" group-by="ch:Employee_ID">
<xsl:sort select="//ch:Effective_Date" order="descending" />
<xsl:copy-of select="." />
</xsl:for-each-group>
</Workers>
</xsl:template>
</xsl:stylesheet>
解决方法
在XSLT 3中,您可以使用currentDocument
函数
sort
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="3.0"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xpath-default-namespace="test/Compensation_History"
exclude-result-prefixes="#all"
expand-text="yes">
<xsl:mode on-no-match="shallow-copy"/>
<xsl:output indent="yes"/>
<xsl:template match="Worker_Entry">
<xsl:copy>
<xsl:apply-templates
select="@*,Employee_ID,(* except Employee_ID)
=> sort((),function($c) { $c/Effective_Date => xs:date() } )
=> reverse()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
作为高级功能需要Saxon 10所有版本或Saxon 9.8及更高版本的PE或EE或Saxon-JS 2。
在您添加的代码中,尽管fn:sort
没有任何意义,因为根元素不在<xsl:for-each-group select="ch:Workers" group-by="ch:Employee_ID">
命名空间中,并且仅对单个元素进行分组,因此您试图对它们进行分组和排序是否提供分组依据表达式会导致该元素具有多个分组键;在这种情况下,您的表达式ch
毫无意义。至于尝试使用ch:Employee_ID
,请在此处使用相对表达式,例如如果您想对组进行分组和排序,xsl:sort
可能很有意义。
如果您确实需要XSLT 2解决方案,那么以下方法应该有效:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:ch="test/Compensation_History" exclude-result-prefixes="xs"
version="2.0">
<xsl:template match="Workers">
<xsl:copy>
<xsl:for-each select="ch:Worker_Entry">
<xsl:copy>
<xsl:copy-of select="ch:Employee_ID"/>
<xsl:for-each select="ch:Compensation_History_Previous_System | ch:Compensation_History_Current_System">
<xsl:sort select="xs:date(ch:Effective_Date)" order="descending"/>
<xsl:copy-of select="."/>
</xsl:for-each>
</xsl:copy>
</xsl:for-each>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。