2010-09-27 6 views
21

J'essaye d'obtenir la valeur d'un nombre à 2 déc. De mon xml.XSL - problème d'arrondi/numéro de format

XML: <Quantity>0.0050</Quantity>

XSL: <xsl:value-of select="format-number($quantity, '####0.00')" />

Cependant semble avoir XSL un problème avec cette valeur et les sorties 0.00 dans une zone de la page et 0.01 dans l'autre. Bien sûr, dans cette situation, il est favorable d'avoir 0.01 sortie dans tous les domaines.

Une autre zone a la valeur 4.221 mais le XSL sort en sortie 4.23.

Je réalise que format-number convertit un nombre en chaîne.

Vous ne savez pas comment résoudre ce problème.


EDIT:

Ok après un peu de bidouiller je trouve que cela fonctionne:

<xsl:value-of select='format-number(round(100*$quantity) div 100 ,"##0.00")' /> 

Via cette website

Comme ce type mentionne les banquiers usages XSL arrondir 'arrondir à des nombres pairs au lieu des plus grands.

La solution ne semble guère élégante et signifie ajouter une tonne de fonctions supplémentaires à un fichier XSL déjà volumineux et compliqué. Sûrement que je manque quelque chose?

+0

Le comportement incohérent que vous décrivez est impair. S'il vous plaît poster votre feuille de style. –

Répondre

17

Vous ne savez pas pourquoi le format serait si incohérent, mais de mémoire la spécification pour cela est ... complexe.

En attendant, vous pouvez utiliser la fonction round (ref). Ce qui est moins que parfait, mais est fonctionnel. Si vous avez besoin d'un nombre particulier de figues sig, vous pouvez utiliser LA PUISSANCE DES MATHS! et faire quelque chose comme:

<xsl:value-of select="round(yournum*100) div 100"/>

+0

Merci pour ça! Je venais de rencontrer la même méthode que celle indiquée ci-dessus. Cela fonctionne mais cela signifie simplement le routage à travers la feuille de style entière et tout changer pour convenir à cela. Yuk! – Julio

+1

Je ne pense pas que cette approche fonctionnera dans tous les cas dans XSLT 1.0 en raison d'erreurs à virgule flottante (veuillez voir ma réponse ci-dessous pour plus de détails). – Giles

14

J'ai eu du mal sans fin avec décimales dans XSLT/XPath 1.0, souvent une combinaison de celui-ci représentant décimaux sous forme de nombres à virgule flottante et à l'aide d'une demi-même arrondissement (banquier arrondi). Malheureusement, l'approche round(yournum*100) div 100 n'a pas fonctionné pour moi, en raison de l'imprécision en virgule flottante. Par exemple, multiplier 1,255 par 100 donne 125,49999999999999 (cela ne dépend pas de l'implémentation car il est supposé être IEEE 754, mais je ne sais pas si toutes les implémentations y adhèrent). Quand arrondi, cela donne alors 125, plutôt que le désiré 126.

J'ai pris l'approche suivante, qui fonctionne (bien que ce soit toujours une zone délicate donc je ne vais pas déclarer trop de confiance!). Cependant, cela dépend de votre moteur XSLT prenant en charge les extensions EXSLT. Il suppose que vous voulez arrondir à deux décimales.

<func:function name="local:RoundHalfUp"> 
    <xsl:param name="number"/> 

    <xsl:choose> 
     <xsl:when test="contains($number, '.')"> 
      <xsl:variable name="decimal" select="estr:split($number, '.')[2]"/> 
      <xsl:choose> 
       <xsl:when test="string-length($decimal) &gt; 2"> 
        <func:result select="format-number(concat($number, '1'), '0.00')"/> 
       </xsl:when> 
       <xsl:otherwise> 
        <func:result select="format-number($number, '0.00')"/> 
       </xsl:otherwise> 
      </xsl:choose> 
     </xsl:when> 
     <xsl:otherwise> 
      <func:result select="format-number($number, '0.00')"/> 
     </xsl:otherwise> 
    </xsl:choose> 

</func:function> 

qui peut être appelé comme:

<xsl:value-of select="local:RoundHalfUp(1.255)"/> 

Les espaces de noms sont:

xmlns:func="http://exslt.org/functions" 
xmlns:estr="http://exslt.org/strings" 
xmlns:local="http://www.acme.org/local_function" 

Il est important de noter que la fonction ajoute un '1', ajoute non 0,001 ou similaire. Vraiment préférable d'utiliser XSLT 2.0 si c'est une option (parce qu'il a un type décimal approprié), mais je sais que ce n'est souvent pas une option (de l'expérience douloureuse!).