XSL:如何对三位数、连字符分隔的值进行排序?
XSL: How can I sort a three digit, hyphen separated value?
问题
我正在尝试对 rule/@id 的整个值进行排序,其中 @id 的值是一个三值,带连字符的字符串,例如“1-10-12”或“10-15-2” .我试过转换成数字,也试过格式化数字,但没有成功。
代码示例输出仅按最左边的数字排序,子值乱序。
XML 来源:
<rule-mapping name="C">
<rule id="0-1-1">
<checker id="checker1"/>
<checker id="checker2"/>
</rule>
<rule id="0-1-10">
<checker id="checker3"/>
</rule>
<rule id="0-1-11">
<checker id="checker4"/>
</rule>
<rule id="15-1-2">
<checker id="checker5"/>
</rule>
<rule id="0-1-12">
<checker id="checker6"/>
</rule>
</rule-mapping>
转换片段:
<tbody>
<xsl:for-each select="rule-mapping/rule">
<xsl:sort select="substring-before(@id, '-')" data-type="number"/>
<xsl:sort select="substring-after(@id, '-')" data-type="number"/>
<row>
<entry>
<xsl:value-of select="@id"/>
</entry>
<entry>
<xsl:for-each select="checker">
<p>
<codeph><xsl:value-of select="@id"/></codeph><xsl:text> </xsl:text>
</p>
</xsl:for-each>
</entry>
</row>
<xsl:text>
</xsl:text>
</xsl:for-each>
</tbody>
预期输出:
<row>
<entry>0-1-1</entry>
<entry>
<p><codeph>checker1</codeph> </p>
<p><codeph>checker2</codeph> </p>
</entry>
</row>
<row>
<entry>0-1-10</entry>
<entry>
<p>
<codeph>checker3</codeph> </p>
</entry>
</row>
<row>
<entry>0-1-11</entry>
<entry>
<p>
<codeph>checker4</codeph> </p>
</entry>
</row>
<row>
<entry>0-1-12</entry>
<entry>
<p>
<codeph>checker6</codeph> </p>
</entry>
</row>
<row>
<entry>15-1-2</entry>
<entry>
<p>
<codeph>checker5</codeph> </p>
</entry>
</row>
提前致谢。
你的想法是正确的,但你需要更进一步:
<xsl:sort select="substring-before(@id, '-')" data-type="number"/>
<xsl:sort select="substring-before(substring-after(@id, '-'), '-')" data-type="number"/>
<xsl:sort select="substring-after(substring-after(@id, '-'), '-')" data-type="number"/>
将这三个 xsl:sort
放在一起,它应该按照您想要的方式排序。
本着 XSLT 2.0 / XPath 2.0 的精神,我会像这样使用单个 <xsl:sort/>
:
<xsl:sort select=
"for $n1 in xs:integer(tokenize(@id, '-')[1]),
$n2 in xs:integer(tokenize(@id, '-')[2]),
$n3 in xs:integer(tokenize(@id, '-')[3])
return
10000*$n1 + 100*$n2 +$n3
"/>
完整的变换变成:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/*">
<xsl:apply-templates select="rule">
<xsl:sort select=
"for $n1 in xs:integer(tokenize(@id, '-')[1]),
$n2 in xs:integer(tokenize(@id, '-')[2]),
$n3 in xs:integer(tokenize(@id, '-')[3])
return
10000*$n1 + 100*$n2 +$n3
"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="rule">
<row>
<entry>
<xsl:value-of select="@id"/>
</entry>
<entry>
<xsl:apply-templates select="checker"/>
</entry>
</row>
<xsl:text>
</xsl:text>
</xsl:template>
<xsl:template match="checker">
<p>
<codeph><xsl:value-of select="@id"/></codeph><xsl:text> </xsl:text>
</p>
</xsl:template>
</xsl:stylesheet>
并且当此转换应用于提供的源 XML 文档时:
<rule-mapping name="C">
<rule id="0-1-1">
<checker id="checker1"/>
<checker id="checker2"/>
</rule>
<rule id="0-1-10">
<checker id="checker3"/>
</rule>
<rule id="0-1-11">
<checker id="checker4"/>
</rule>
<rule id="15-1-2">
<checker id="checker5"/>
</rule>
<rule id="0-1-12">
<checker id="checker6"/>
</rule>
</rule-mapping>
产生了想要的正确结果:
<row>
<entry>0-1-1</entry>
<entry>
<p>
<codeph>checker1</codeph> </p>
<p>
<codeph>checker2</codeph> </p>
</entry>
</row>
<row>
<entry>0-1-10</entry>
<entry>
<p>
<codeph>checker3</codeph> </p>
</entry>
</row>
<row>
<entry>0-1-11</entry>
<entry>
<p>
<codeph>checker4</codeph> </p>
</entry>
</row>
<row>
<entry>0-1-12</entry>
<entry>
<p>
<codeph>checker6</codeph> </p>
</entry>
</row>
<row>
<entry>15-1-2</entry>
<entry>
<p>
<codeph>checker5</codeph> </p>
</entry>
</row>
问题
我正在尝试对 rule/@id 的整个值进行排序,其中 @id 的值是一个三值,带连字符的字符串,例如“1-10-12”或“10-15-2” .我试过转换成数字,也试过格式化数字,但没有成功。
代码示例输出仅按最左边的数字排序,子值乱序。
XML 来源:
<rule-mapping name="C">
<rule id="0-1-1">
<checker id="checker1"/>
<checker id="checker2"/>
</rule>
<rule id="0-1-10">
<checker id="checker3"/>
</rule>
<rule id="0-1-11">
<checker id="checker4"/>
</rule>
<rule id="15-1-2">
<checker id="checker5"/>
</rule>
<rule id="0-1-12">
<checker id="checker6"/>
</rule>
</rule-mapping>
转换片段:
<tbody>
<xsl:for-each select="rule-mapping/rule">
<xsl:sort select="substring-before(@id, '-')" data-type="number"/>
<xsl:sort select="substring-after(@id, '-')" data-type="number"/>
<row>
<entry>
<xsl:value-of select="@id"/>
</entry>
<entry>
<xsl:for-each select="checker">
<p>
<codeph><xsl:value-of select="@id"/></codeph><xsl:text> </xsl:text>
</p>
</xsl:for-each>
</entry>
</row>
<xsl:text>
</xsl:text>
</xsl:for-each>
</tbody>
预期输出:
<row>
<entry>0-1-1</entry>
<entry>
<p><codeph>checker1</codeph> </p>
<p><codeph>checker2</codeph> </p>
</entry>
</row>
<row>
<entry>0-1-10</entry>
<entry>
<p>
<codeph>checker3</codeph> </p>
</entry>
</row>
<row>
<entry>0-1-11</entry>
<entry>
<p>
<codeph>checker4</codeph> </p>
</entry>
</row>
<row>
<entry>0-1-12</entry>
<entry>
<p>
<codeph>checker6</codeph> </p>
</entry>
</row>
<row>
<entry>15-1-2</entry>
<entry>
<p>
<codeph>checker5</codeph> </p>
</entry>
</row>
提前致谢。
你的想法是正确的,但你需要更进一步:
<xsl:sort select="substring-before(@id, '-')" data-type="number"/>
<xsl:sort select="substring-before(substring-after(@id, '-'), '-')" data-type="number"/>
<xsl:sort select="substring-after(substring-after(@id, '-'), '-')" data-type="number"/>
将这三个 xsl:sort
放在一起,它应该按照您想要的方式排序。
本着 XSLT 2.0 / XPath 2.0 的精神,我会像这样使用单个 <xsl:sort/>
:
<xsl:sort select=
"for $n1 in xs:integer(tokenize(@id, '-')[1]),
$n2 in xs:integer(tokenize(@id, '-')[2]),
$n3 in xs:integer(tokenize(@id, '-')[3])
return
10000*$n1 + 100*$n2 +$n3
"/>
完整的变换变成:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/*">
<xsl:apply-templates select="rule">
<xsl:sort select=
"for $n1 in xs:integer(tokenize(@id, '-')[1]),
$n2 in xs:integer(tokenize(@id, '-')[2]),
$n3 in xs:integer(tokenize(@id, '-')[3])
return
10000*$n1 + 100*$n2 +$n3
"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="rule">
<row>
<entry>
<xsl:value-of select="@id"/>
</entry>
<entry>
<xsl:apply-templates select="checker"/>
</entry>
</row>
<xsl:text>
</xsl:text>
</xsl:template>
<xsl:template match="checker">
<p>
<codeph><xsl:value-of select="@id"/></codeph><xsl:text> </xsl:text>
</p>
</xsl:template>
</xsl:stylesheet>
并且当此转换应用于提供的源 XML 文档时:
<rule-mapping name="C">
<rule id="0-1-1">
<checker id="checker1"/>
<checker id="checker2"/>
</rule>
<rule id="0-1-10">
<checker id="checker3"/>
</rule>
<rule id="0-1-11">
<checker id="checker4"/>
</rule>
<rule id="15-1-2">
<checker id="checker5"/>
</rule>
<rule id="0-1-12">
<checker id="checker6"/>
</rule>
</rule-mapping>
产生了想要的正确结果:
<row>
<entry>0-1-1</entry>
<entry>
<p>
<codeph>checker1</codeph> </p>
<p>
<codeph>checker2</codeph> </p>
</entry>
</row>
<row>
<entry>0-1-10</entry>
<entry>
<p>
<codeph>checker3</codeph> </p>
</entry>
</row>
<row>
<entry>0-1-11</entry>
<entry>
<p>
<codeph>checker4</codeph> </p>
</entry>
</row>
<row>
<entry>0-1-12</entry>
<entry>
<p>
<codeph>checker6</codeph> </p>
</entry>
</row>
<row>
<entry>15-1-2</entry>
<entry>
<p>
<codeph>checker5</codeph> </p>
</entry>
</row>