2009-10-08 38 views
4

我想按升序對這些元素進行排序,但用空值排序而不是第一個,這似乎是默認情況下xslt所做的。我設法做到這一點,但不知道是否有更好的方法。這是我的例子。如何將xsl按空值升序排序最後

<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> 

,其表明了所需的輸出:我目前使用<xsl:sort select="node() = false()"/>來測試它是null,則使用排序訂購null元素

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

最後(空將是1,而不是null將爲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) 
) 
) 
+0

這是聰明的,我喜歡它。我將不得不嘗試更頻繁地使用它; ;-) – 2009-10-08 16:58:05

+2

這樣做是將布爾值轉換爲1或0,以便您可以對該值進行排序。但是你*已經可以對布爾值進行排序了;他們從錯誤到真實。如果你只是對'not(boolean(text()))進行排序,你將首先得到非空元素,然後是空元素。 – 2009-10-09 02:38:22

+1

有趣的是,我沒有想到這一點。可以簡化爲'boolean(text())',然後可以通過升序/降序來控制排序順序。 – Tomalak 2009-10-09 07:07:19