2009-10-08 6 views
4

Je veux trier ces éléments dans l'ordre croissant, mais avec les nulls dernier plutôt que le premier qui semble être ce que xslt fait par défaut. J'ai réussi à le faire mais je me demande s'il y a un meilleur moyen. Voici mon exemple.comment trier par ordre croissant xsl croissant avec les 0s dernières

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

Ce qui donne la puissance requise de:

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

J'utilise actuellement <xsl:sort select="node() = false()"/> pour tester étant nul puis en utilisant une sorte de commander les éléments nuls dernier (null sera 1 et non null sera 0 donc il les ordonne correctement).

Quelqu'un peut-il suggérer quelque chose de mieux que cela?

Répondre

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> 

Ce:

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

cause soit '0' ou '1', selon qu'il y est un nœud de texte enfant, ou non. C'est la concaténation de deux chaînes s'excluant mutuellement - l'homme pauvre si/alors/autrement dans XPath 1.0.

Le produit boolean(text())true ou false, qui est ensuite converti en un numéro pour substring(). Les valeurs booléennes sont converties en 1 ou 0, respectivement.

La version plus complète de la passe au-dessus comme ceci:

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

C'est intelligent, je l'aime. Je vais devoir essayer de l'utiliser plus souvent ... ;-) –

+2

Ce que cela fait est de convertir une valeur booléenne en 1 ou 0, de sorte que vous pouvez trier sur cette valeur. Mais vous * pouvez déjà * trier les valeurs booléennes; ils trient de faux à vrai. Si vous ne faites que trier 'non (boolean (text()))', vous obtiendrez d'abord les éléments non vides, puis les vides. –

+1

Intéressant, je n'y ai pas pensé. Pourrait être simplifié en 'boolean (text())', l'ordre de tri pourrait ensuite être contrôlé via l'ascendant/descendant. – Tomalak

Questions connexes