注意: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> 的所有子项进行排序来覆盖身份转换。
再次注意,此解决方案假定您的原始断言——“代码有四个字符和四个数字”——是(并且永远是)正确的。
二。 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>
说明:
三。 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() 方法很可能更有效。