我必须按数字顺序整理代码。代码有四个字符和四个数字。
例如,
COMP2100
COMP2400
COMP3410
LAWS2202
LAWS2250
当我这样做时<xsl:sort select="code" order="ascending" />
,它会显示上面的结果。
但是,我希望它是“数字顺序”,即
COMP2100
LAWS2202
COMP2250
COMP2400
COMP3410
我该怎么做呢?
注意: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
(如果不是)最基本的设计模式之一—— 将源 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()
方法很可能更有效。
提供的 XSLT 代码中有两个明显的错误:
用于选择元素的命名空间与提供的 XML 文档的默认命名空间不同。只需更改:xmlns:xsi="file://Volumes/xxxxxxx/Assignment"
到xmlns:xsi="file://Volumes/xxxxxxx/Assignment"
.
目前的排序不是数字的。改变:
<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>