如何使用XSLT按TRANNUM列对输出CSV文件进行升序排序?
问题:XSLT转换XML生成CSV时按TRANNUM升序排序的需求
我正在使用XSLT转换XML文件,期望输出的CSV文件按TRANNUM列升序排列,TRANNUM可选值为10、11、12,要求TRANNUM=10的行优先,依次为11、12的行。当前XSLT可正常运行,但实际是按tns:Company/tns:Code(值为RETGP、RTLPM、RETRT)排序,而非TRANNUM值。
待修改的XSLT代码片段
<?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:math="http://www.w3.org" xmlns:wd="http://" xmlns:tns="http://" xmlns:xtt="urn:" exclude-result-prefixes="xs math wd tns xtt" version="3.0"> <xsl:param name="p.source"></xsl:param> <xsl:output method="text" indent="yes"/> <xsl:strip-space elements="*"/> <xsl:template match="tns:OutboundFile"> <header1>FinJournals
TRANNUM,DATE,PROPERTY,ACCOUNT,POSTMONTH,BOOKNUM,AMOUNT,REMARK,REF,DESC,SEGMENT2,DISPLAYTYPE,ReverseNextMonth</header1> <JournalEntry> <xsl:for-each-group select="tns:Journal_Entry/tns:Journal_Line[tns:Ledger_Account != '888888']" group-by="string-join((tns:Company/tns:Code,tns:Ledger_Account,description),'+')"> <xsl:sort select="tns:Company/tns:Code" data-type="text" order="ascending"/> <xsl:if test="format-number(sum(current-group()/tns:Ledger_Debit_Amount) - sum(current-group()/tns:Ledger_Credit_Amount),'#0.00') != '0.00'"> <JournalLine> <xsl:text>
</xsl:text> <TRANNUM> <xsl:choose> <xsl:when test="tns:Company/tns:Code = 'RETGP'">10</xsl:when> <xsl:when test="tns:Company/tns:Code = 'RTLPM'">11</xsl:when> <xsl:when test="tns:Company/tns:Code = 'RETRT'">12</xsl:when> </xsl:choose> </TRANNUM><xsl:text>,</xsl:text> <DATE><xsl:value-of select="format-date(current-date(),'[M01]/[D01]/[Y0001]')"/></DATE><xsl:text>,</xsl:text> <PROPERTY> <xsl:choose> <xsl:when test="tns:Company/tns:Code = 'RETGP'">22000</xsl:when> <xsl:when test="tns:Company/tns:Code = 'RTLPM'">26000</xsl:when> <xsl:when test="tns:Company/tns:Code = 'RETRT'">23000</xsl:when> </xsl:choose> </PROPERTY><xsl:text>,</xsl:text>
当前输出示例
TRANNUM,DATE,PROPERTY,ACCOUNT,POSTMONTH 10,01/11/2023,22000,720010,01/13/2023,1 10,01/11/2023,22000,720025,01/13/2023,1 10,01/11/2023,22000,211070,01/13/2023,1 10,01/11/2023,22000,720005,01/13/2023,1 10,01/11/2023,22000,211070,01/13/2023,1 12,01/11/2023,23000,720025,01/13/2023,1 12,01/11/2023,23000,211070,01/13/2023,1 11,01/11/2023,26000,211070,01/13/2023,1 11,01/11/2023,26000,211010,01/13/2023,1 11,01/11/2023,26000,211065,01/13/2023,1 11,01/11/2023,26000,211010,01/13/2023,1 11,01/11/2023,26000,211070,01/13/2023,1 11,01/11/2023,26000,211015,01/13/2023,1
期望输出示例
TRANNUM,DATE,PROPERTY,ACCOUNT,POSTMONTH 10,01/11/2023,22000,211070,01/13/2023,1 10,01/11/2023,22000,720025,01/13/2023,1 10,01/11/2023,22000,211070,01/13/2023,1 10,01/11/2023,22000,720010,01/13/2023,1 10,01/11/2023,22000,720025,01/13/2023,1 11,01/11/2023,26000,211070,01/13/2023,1 11,01/11/2023,26000,211010,01/13/2023,1 11,01/11/2023,26000,211065,01/13/2023,1 11,01/11/2023,26000,211010,01/13/2023,1 11,01/11/2023,26000,211015,01/13/2023,1 11,01/11/2023,26000,211070,01/13/2023,1 12,01/11/2023,23000,720005,01/13/2023,1 12,01/11/2023,23000,211070,01/13/2023,1
解决方案
问题出在当前的<xsl:sort>是按tns:Company/tns:Code的文本顺序排序,而文本排序中RETRT(对应TRANNUM12)在RTLPM(对应TRANNUM11)之前,导致输出中12的行排在11前面。
只需将原有的排序规则替换为直接映射Code到对应的TRANNUM数值,按数字排序即可:
XSLT 3.0版本(支持choose()函数)
<!-- 替换原来的<xsl:sort> --> <xsl:sort select=" choose( tns:Company/tns:Code = 'RETGP', 10, tns:Company/tns:Code = 'RTLPM', 11, tns:Company/tns:Code = 'RETRT', 12 )" data-type="number" order="ascending"/>
XSLT 2.0及以下版本
<!-- 替换原来的<xsl:sort> --> <xsl:sort data-type="number" order="ascending"> <xsl:choose> <xsl:when test="tns:Company/tns:Code = 'RETGP'">10</xsl:when> <xsl:when test="tns:Company/tns:Code = 'RTLPM'">11</xsl:when> <xsl:when test="tns:Company/tns:Code = 'RETRT'">12</xsl:when> </xsl:choose> </xsl:sort>
修改后,分组后的行会按照TRANNUM的数值10→11→12的顺序排列,符合期望输出要求。
内容的提问来源于stack exchange,提问作者Kayode Olanrewaju Mosaku
相关产品推荐
相关产品推荐

