如何xsl以null为最后升序排序

时间:2009-10-08 15:26:44

标签: xml xslt

我想按升序对这些元素进行排序,但是空值最后而不是第一个,这似乎是xslt默认执行的操作。我设法做到这一点,但想知道是否有更好的方法。这是我的例子。

<b>
    <c>2</c>
    <c>1</c>
    <c>3</c>
    <c></c>
    <c>15</c>
    <c>11</c>
    <c></c>
    <c>43</c>
    <c>4</c>
</b>


<xsl:template match="/">
    <xsl:for-each select="b/c">
        <xsl:sort select="node() = false()"/>
        <xsl:sort select="." data-type="number"/>
        Row<xsl:value-of select="position()"/>:<xsl:value-of select="."/>
    </xsl:for-each>
</xsl:template>

其中提供了所需的输出:

Row1:1
Row2:2
Row3:3
Row4:4
Row5:11
Row6:15
Row7:43
Row8:
Row9:  

我正在使用<xsl:sort select="node() = false()"/>来测试它是否为null然后使用排序对null元素进行最后排序(null将为1而非null将为0,因此它会正确排序它们)。

有人能提出比这更好的建议吗?

1 个答案:

答案 0 :(得分:4)

<xsl:template match="/">
  <xsl:for-each select="b/c">
    <xsl:sort select="concat(
      substring('1', 1, boolean(text())),
      substring('0', 1, not(boolean(text())))
    )" />
    <xsl:sort select="." data-type="number"/>
    <xsl:text>Row</xsl:text>
    <xsl:value-of select="position()"/>
    <xsl:text>:</xsl:text>
    <xsl:value-of select="."/>
    <xsl:text>&#10;</xsl:text>
  </xsl:for-each>
</xsl:template>

此:

concat(
  substring('1', 1, boolean(text()) ),
  substring('0', 1, not(boolean(text())))
)

生成“0”或“1”,具体取决于是否为子文本节点。它是两个相互排斥的字符串的串联 - 在XPath 1.0中是穷人的if / then / else。

boolean(text())生成truefalse,然后将其转换为substring()的数字。布尔值分别转换为1或0。

以上更完整的版本是这样的:

concat(
  substring(
    $if_str, 
    1, 
    boolean($condition) * string-length($if_str)
  ),
  substring(
    $else_str, 
    1, 
    not(boolean($condition)) * string-length($else_str)
  )
)