[英]Xml sorting with xslt
我正在尝试使用XSLT对基于JobDate
XML进行排序。
例如,使用给定的test.xml :
<ROOT>
<Employees>
<EmployeName JobDate="1-jan-2015 to 1-jan-2016">
<Name>A</Name>
</EmployeName>
<EmployeName1 JobDate="2-nov-2014 to 5-may-2015">
<Name>B</Name>
</EmployeName1>
</Employees>
</Root>
XSLT代码:
<xsl:for-each select="ROOT/Employees">
<xsl:for-each select="*">
<xsl:sort select="." order="descending"/>
<xsl:if test="fn:exists(EmployeName1)">
<fo:table>
<fo:table-column column-width="30mm"/>
<fo:table-column column-width="30mm"/>
<fo:table-body start-indent="0pt">
<xsl:for-each select="EmployeName1">
<fo:table-row>
<fo:table-cell number-columns-spanned="8" padding="-1" display-align="center"> <fo:block-container overflow="hidden"> <fo:block text-align="left"> <fo:inline color="black" font-family="Tondo Corp" font-size="9pt" font-weight="bold"> <xsl:text>EmployeName1 - </xsl:text> </fo:inline> <xsl:for-each select="@JobDate"> <altova:inline-container-substitute color="black" font-family="Tondo Corp" font-size="9pt"> <fo:inline> <xsl:value-of select="string(.)"/> </fo:inline> </altova:inline-container-substitute> </xsl:for-each> </fo:block> </fo:block-container> </fo:table-cell>
</fo:table-row>
<fo:table-row>
<fo:table>
<fo:table-column column-width="30mm"/>
<fo:table-column column-width="30mm"/>
<fo:table-body start-indent="0pt">
<xsl:for-each select="Name">
<fo:table-row>
<fo:table-cell padding="0" display-align="center" altova:is-body-cell="true"> <fo:block-container overflow="hidden"><fo:block text-align="left"> <xsl:for-each select="upper-case(Name)"> <altova:inline-container-substitute color="red" font-family="Tondo Corp" font-size="7pt" font-weight="bold" margin-bottom="0mm" margin-top="0mm" padding-bottom="0mm" padding-top="0mm"> <xsl:choose> <xsl:when test=". instance of element() or . instance of document-node()"> <xsl:apply-templates/> </xsl:when> <xsl:otherwise> <xsl:value-of select="."/> </xsl:otherwise> </xsl:choose> </altova:inline-container-substitute> </xsl:for-each> </fo:block></fo:block-container> </fo:table-cell
</fo:table-row>
</xsl:for-each>
</fo:table>
</fo:table>
</fo:table-row>
</xsl:for-each>
</fo:table-body>
</fo:table>
</xsl:if>
<xsl:if test="fn:exists(EmployeName)">
<fo:table>
<fo:table-column column-width="30mm"/>
<fo:table-column column-width="30mm"/>
<fo:table-body start-indent="0pt">
<xsl:for-each select="EmployeName1">
<fo:table-row>
<fo:table-cell number-columns-spanned="8" padding="-1" display-align="center"> <fo:block-container overflow="hidden"> <fo:block text-align="left"> <fo:inline color="black" font-family="Tondo Corp" font-size="9pt" font-weight="bold"> <xsl:text>EmployeName - </xsl:text> </fo:inline> <xsl:for-each select="@JobDate"> <altova:inline-container-substitute color="black" font-family="Tondo Corp" font-size="9pt"> <fo:inline> <xsl:value-of select="string(.)"/> </fo:inline> </altova:inline-container-substitute> </xsl:for-each> </fo:block>
</fo:block-container>
</fo:table-cell>
</fo:table-row>
<fo:table-row>
<fo:table>
<fo:table-column column-width="30mm"/>
<fo:table-column column-width="30mm"/>
<fo:table-body start-indent="0pt">
<xsl:for-each select="Name">
<fo:table-row>
<fo:table-cell padding="0" display-align="center" altova:is-body-cell="true">
<fo:block-container overflow="hidden"> <fo:block text-align="left"> <xsl:for-each select="upper-case(Name)"> <altova:inline-container-substitute color="red" font-family="Tondo Corp" font-size="7pt" font-weight="bold" margin-bottom="0mm" margin-top="0mm" padding-bottom="0mm" padding-top="0mm"> <xsl:choose> <xsl:when test=". instance of element() or . instance of document-node()"> <xsl:apply-templates/>
</xsl:when> <xsl:otherwise> <xsl:value-of select="."/> </xsl:otherwise> </xsl:choose> </altova:inline-container-substitute> </xsl:for-each>
</fo:block>
</fo:block-container>
</fo:table-cell
</fo:table-row>
</xsl:for-each>
</fo:table>
</fo:table>
</fo:table-row>
</xsl:for-each>
</fo:table-body>
</fo:table>
</xsl:if>
</xsl:for-each>
</xsl:for-each>
我需要帮助对此xml进行排序,在此先感谢。
要在XSLT 1.0中做到这一点,您将需要进行一些相当复杂的字符串操作,因为您需要首先按年份,然后按月份,然后按日期进行排序。 月份是最棘手的,因为您实际上需要按月份编号而不是名称进行排序。
这是一种您可以做到的方式
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="html" doctype-public="XSLT-compat" omit-xml-declaration="yes" encoding="UTF-8" indent="yes" />
<xsl:variable name="years" select="'jan-feb-mar-apr-may-jun-jul-aug-sep-oct-nov-dec'" />
<xsl:template match="/">
<table>
<xsl:for-each select="ROOT/Employees">
<xsl:for-each select="*">
<xsl:sort select="substring-after(substring-after(substring-before(@JobDate, ' '), '-'), '-')" order="ascending" data-type="number"/>
<xsl:sort select="string-length(substring-before($years, lower-case(substring-before(substring-after(@JobDate, '-'), '-'))))" order="ascending" data-type="number"/>
<xsl:sort select="substring-before(@JobDate, '-')" order="ascending" data-type="number"/>
<row>
<cell><xsl:value-of select="Name" /></cell>
<cell><xsl:value-of select="@JobDate" /></cell>
</row>
</xsl:for-each>
</xsl:for-each>
</table>
</xsl:template>
</xsl:stylesheet>
当应用于此输入时...
<ROOT>
<Employees>
<EmployeName JobDate="1-nov-2014 to 1-jan-2016">
<Name>B</Name>
</EmployeName>
<EmployeName1 JobDate="1-nov-2015 to 5-may-2016">
<Name>C</Name>
</EmployeName1>
<EmployeName2 JobDate="2-aug-2014 to 5-may-2015">
<Name>A</Name>
</EmployeName2>
</Employees>
</ROOT>
输出如下
<table>
<row>
<cell>A</cell>
<cell>2-aug-2014 to 5-may-2015</cell>
</row>
<row>
<cell>B</cell>
<cell>1-nov-2014 to 1-jan-2016</cell>
</row>
<row>
<cell>C</cell>
<cell>1-nov-2015 to 5-may-2016</cell>
</row>
</table>
请注意,这是假设月份总是小写
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.