4

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

例如,

COMP2100
COMP2400
COMP3410
LAWS2202
LAWS2250

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

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

COMP2100
LAWS2202
COMP2250
COMP2400
COMP3410

我该怎么做呢?

4

2 回答 2

9

注意: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>

解释:

  • —— XSLTIdentity Transform(如果不是)最基本的设计模式之一—— 将源 XML 文档中的所有节点按原样复制到结果 XML 文档中。
  • <t>一个模板通过根据字符串中从位置 5 到字符串末尾的字符对 的所有子项进行排序来覆盖身份转换。

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


二、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 首次向我展示)<i>在排序之前从每个元素的值中删除所有非数字字符。

三、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()方法很可能更有效。

于 2012-09-16T19:33:01.177 回答
3

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

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

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

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

到:

   <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>
于 2012-09-16T20:27:47.980 回答