xsl:sort:按数值排序

时间:2012-09-16 19:21:40

标签: xslt sorting numerical

我必须按数字顺序整理代码。 代码有四个字符和四个数字。

例如,

COMP2100
COMP2400
COMP3410
LAWS2202
LAWS2250

当我做<xsl:sort select="code" order="ascending" />时 它显示在上面的结果。

但是,我希望它是'数字顺序'

COMP2100
LAWS2202
COMP2250
COMP2400
COMP3410

我该怎么做?

2 个答案:

答案 0 :(得分:6)

注意:OP现在提供了示例XML。以下理论可以简单地适应这种XML。

<强>予。 XSLT 1.0(第1部分)

这是一个简单的解决方案,假设您的断言(“代码有四个字符和四个数字”)将始终如此:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
  <xsl:output omit-xml-declaration="no" indent="yes" />
  <xsl:strip-space elements="*" />

  <xsl:variable name="vNums" select="'1234567890'" />

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

  <xsl:template match="/*">
    <t>
      <xsl:apply-templates>
        <xsl:sort select="substring(., 5)"
          data-type="number" />
      </xsl:apply-templates>
    </t>
  </xsl:template>
</xsl:stylesheet> 

...应用于想象的XML文档,随机排列:

<?xml version="1.0" encoding="utf-8"?>
<t>
  <i>COMP3410</i>
  <i>LAWS2202</i>
  <i>COMP2400</i>
  <i>COMP2100</i>
  <i>LAWS2250</i>
</t>

...产生了正确的结果:

<?xml version="1.0" encoding="utf-8"?>
<t>
  <i>COMP2100</i>
  <i>LAWS2202</i>
  <i>LAWS2250</i>
  <i>COMP2400</i>
  <i>COMP3410</i>
</t>

<强>解释

  • Identity Transform - XSLT中最基本的设计模式之一(如果不是 ) - 将所有节点从源XML文档复制到结果XML文档中
  • 一个模板通过根据字符串中从第5位到字符串结尾的字符对<t>的所有子项进行排序来覆盖标识变换。

再次注意,这个解决方案假定你的原始断言 - “代码有四个字符和四个数字” - 是(并且总是会)为真。


<强> II。 XSLT 1.0(第2部分)

(可能)更安全的解决方案是假设<i>节点内的不同位置可能存在大量非数字字符。在这种情况下,这个XSLT:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
  <xsl:output omit-xml-declaration="no" indent="yes" />
  <xsl:strip-space elements="*" />

  <xsl:variable name="vNums" select="'1234567890'" />

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

  <xsl:template match="/*">
    <t>
      <xsl:apply-templates>
        <xsl:sort select="translate(., translate(., $vNums, ''), '')"
          data-type="number" />
      </xsl:apply-templates>
    </t>
  </xsl:template>
</xsl:stylesheet>

...提供了相同的结果:

<?xml version="1.0" encoding="utf-8"?>
<t>
  <i>COMP2100</i>
  <i>LAWS2202</i>
  <i>LAWS2250</i>
  <i>COMP2400</i>
  <i>COMP3410</i>
</t>

<强>解释

  • 再次使用Identity Transform
  • 在这种情况下,附加模板使用所谓的Double Translate Method(由Michael Kay首先提出并由Dimitre Novatchev首次向我显示)从每个{{1的值中删除所有非数字字符排序前的元素。

<强> III。 XSLT 2.0解决方案

这是一个可能的XSLT 2.0解决方案,与XSLT 1.0解决方案的第2部分非常相似;它只是用XPath 2.0处理正则表达式的能力取代了Double Translate方法:

<i>

请注意,您无需 在XPath 2.0中使用正则表达式; Double Translate方法与XPath 1.0一样有效。但是,<xsl:sort select="replace(., '[^\d]', '')" data-type="number" /> 方法最有可能更有效。

答案 1 :(得分:3)

提供的XSLT代码中有两个明显的错误

  1. 用于选择元素的命名空间与提供的XML文档的默认命名空间不同。只需将xmlns:xsi="file://Volumes/xxxxxxx/Assignment"更改为xmlns:xsi="file://Volumes/xxxxxxx/Assignment"

  2. 目前的排序不是数字。变化:

    <xsl:sort select="xsi:code" order="ascending" />

  3. 为:

       <xsl:sort select="substring(xsi:code, 5)" data-type="number" />
    

    完整转化

    <xsl:stylesheet version="1.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     xmlns:xs="http://www.w3.org/2001/XMLSchema"
     xmlns:fn="http://www.w3.org/2005/xpath-functions"
     xmlns:xsi="file://Volumes/u4783938/Assignment">
    <xsl:template match="/">
        <html>
        <head>
            <title> Course Catalogue </title>
        </head>
        <body bgcolor="#FF9999">
            <h1> <div style="text-align:center"> Course Catalogue </div> </h1>
            <xsl:for-each select="xsi:catalogue/xsi:course">
            <xsl:sort select="substring(xsi:code, 5)"
             data-type="number" />
            <div style="width:1000px;margin-bottom:4px;color:white;background-color:#F36;text-align:justify;border:outset;margin-left:auto;margin-right:auto;">
                <xsl:apply-templates select="xsi:code" />
                <br />
                <xsl:apply-templates select="xsi:title" />
                <br />
                <xsl:apply-templates select="xsi:year" />
                <br />
                <xsl:apply-templates select="xsi:science" />
                <br />
                <xsl:apply-templates select="xsi:area" />
                <br />
                <xsl:apply-templates select="xsi:subject" />
                <br />
                <xsl:apply-templates select="xsi:updated" />
                <br />
                <xsl:apply-templates select="xsi:unit" />
                <br />
                <xsl:apply-templates select="xsi:description" />
                <br />
                <xsl:apply-templates select="xsi:outcomes" />
                <br />
                <xsl:apply-templates select="xsi:incompatibility" />
            </div>
            </xsl:for-each>
        </body>
        </html>
    </xsl:template>
    </xsl:stylesheet>
    

    并在应用于此XML文档时

    <catalogue xmlns="file://Volumes/u4783938/Assignment"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="file://Volumes/u4443554/Assignment/courses.xsd">
        <course>
            <code>ABCD3410</code>
            <title> Information Technology in Electronic Commerce </title>
            <year>later year</year>
            <science>C</science>
            <area> Research School of Computer Science </area>
            <subject> Computer Science </subject>
            <updated>2012-03-13T13:12:00</updated>
            <unit>6</unit>
            <description>Tce </description>
            <outcomes>Up trCommerce. </outcomes>
            <incompatibility>COMP1100</incompatibility>
        </course>
        <course>
            <code>COMP2011</code>
            <title> Course 2011 </title>
            <year>Year 2011</year>
            <science>C++</science>
            <area> Research School of Computer Science </area>
            <subject> Computer Science </subject>
            <updated>2012-03-13T13:12:00</updated>
            <unit>6</unit>
            <description>Tce </description>
            <outcomes>Up trCommerce. </outcomes>
            <incompatibility>COMP1100</incompatibility>
        </course>
    </catalogue>
    

    现在,生成的结果按课程代码的数字部分正确排序:

    <html xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:xsi="file://Volumes/u4783938/Assignment">
       <head>
          <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    
          <title> Course Catalogue </title>
       </head>
       <body bgcolor="#FF9999">
          <h1>
             <div style="text-align:center"> Course Catalogue </div>
          </h1>
          <div style="width:1000px;margin-bottom:4px;color:white;background-color:#F36;text-align:justify;border:outset;margin-left:auto;margin-right:auto;">COMP2011<br> Course 2011 <br>Year 2011<br>C++<br> Research School of Computer Science <br> Computer Science <br>2012-03-13T13:12:00<br>6<br>Tce <br>Up trCommerce. <br>COMP1100
          </div>
          <div style="width:1000px;margin-bottom:4px;color:white;background-color:#F36;text-align:justify;border:outset;margin-left:auto;margin-right:auto;">ABCD3410<br> Information Technology in Electronic Commerce <br>later year<br>C<br> Research School of Computer Science <br> Computer Science <br>2012-03-13T13:12:00<br>6<br>Tce <br>Up trCommerce. <br>COMP1100
          </div>
       </body>
    </html>