【问题标题】:xsl:sort: sorting by numeric valuexsl:sort:按数值排序
【发布时间】:2012-09-09 02:51:37
【问题描述】:

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

例如,

COMP2100
COMP2400
COMP3410
LAWS2202
LAWS2250

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

但是,我希望它是“数字顺序”,即

COMP2100
LAWS2202
COMP2250
COMP2400
COMP3410

我该怎么做?

【问题讨论】:

    标签: xslt sorting numerical


    【解决方案1】:

    注意: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 到字符串末尾的字符对 &lt;t&gt; 的所有子项进行排序来覆盖身份转换。

    再次注意,此解决方案假定您的原始断言——“代码有四个字符和四个数字”——是(并且永远是)正确的。


    二。 XSLT 1.0(第 2 部分)

    一个(可能)更安全的解决方案是假设&lt;i&gt; 节点内的不同位置可能有许多非数字字符。在这种情况下,这个 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 首次向我展示)从之前的每个 &lt;i&gt; 元素的值中删除所有非数字字符排序。

    三。 XSLT 2.0 解决方案

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

    <xsl:sort select="replace(., '[^\d]', '')" data-type="number" />
    

    请注意,在 XPath 2.0 中,您绝不需要使用正则表达式; Double Translate Method 与 XPath 1.0 中的效果一样好。但是,replace() 方法很可能更有效。

    【讨论】:

    • 嗨,阿巴赫,感谢您提供的信息!我已经提供了我的 XML 和 XSL,你能告诉我哪一个在效率方面最有效吗?谢谢!
    • @JaneDoe - 没问题!鉴于您使用的是 XSLT 1.0,XSLT 1.0 解决方案 #1 可能是最有效的。但是,除非您正在处理非常大的文档,否则 XSLT 1.0 解决方案 #1 和 XSLT 1.0 解决方案 #2 将非常相似。我的建议是根据您未来的需求进行选择;同样,XSLT 1.0 解决方案 #2 更简单。
    • @ABach,您的 XSLT 2.0 解决方案存在明显错误——请始终通过在代表性数据上实际运行解决方案并确认它们产生正确结果来验证您的解决方案。此外,XSLT 1.0 解决方案不适用于 OP 提供的特定 XML 文档结构。
    • 对于这样的事情怎么样:stackoverflow.com/questions/33372683/…(它是智能表单的一部分,所以我不能有多个相同的字段值)
    【解决方案2】:

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

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

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

      &lt;xsl:sort select="xsi:code" order="ascending" /&gt;

    到:

       <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>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-01-08
      • 2015-06-02
      • 1970-01-01
      • 2011-12-24
      • 2017-10-15
      • 2012-06-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多