2009-10-08 2 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> 

Что дает необходимый выход:

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

Я в настоящее время с помощью <xsl:sort select="node() = false()"/>, чтобы проверить это быть нулевым, тогда с помощью своего рода заказать нулевые элементы последнего (нуль будет 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', в зависимости от есть ли текстовый дочерний узел, или нет. Это конкатенация двух взаимоисключающих строк - бедный человек, если/then/else в XPath 1.0.

boolean(text()) производит true или false, который затем преобразуется в число для 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

Это умный, мне это нравится. Мне придется попробовать и использовать его чаще ... ;-) –

+2

Что это значит, это преобразование логического значения в 1 или 0, так что вы можете сортировать по этому значению. Но вы * уже можете * сортировать по логическим значениям; они сортируются от ложных до истинных. Если вы просто сортируете 'not (boolean (text())), вы сначала получите непустые элементы, за которыми следуют пустые. –

+1

Интересно, я об этом не думал. Может быть упрощено до 'boolean (text())', порядок сортировки может контролироваться по возрастанию/убыванию. – Tomalak

Смежные вопросы