XSLT Décimal mise en forme basée sur XML d'entrée

J'ai une situation où mes fichiers XSLT doit afficher les prix alongwith décimales, sous certaines conditions, selon que l'entrée XML contient des décimales ou pas. Donc, je peux recevoir des fichiers XML avec deux types de valeurs - XML contiendra tous les prix mis en forme avec des décimales jusqu'à deux endroits (j'appelle cela une "Virgule-XML") ou les prix seront arrondis à l'entier le plus proche (j'appelle cela un "Integer-XML").

Mon problème est que j'ai besoin de revoir aussi peu que possible dans les fichiers XSLT et pourtant leur permettre d'appliquer la transformation en XHTML dans le même format que le XML d'entrée. Pour ce faire, j'ai mis en place et a proposé trois lignes directrices pour mon équipe:

  1. Supprimer tous les format-number() appels de fonction lorsque la valeur est calculée pour les calculs ou stockée dans une variable. Utilisation number(<value>) à la place. Cependant, certaines conditions s'appliquent à cette règle (Voir ci-dessous).
  2. Lorsque la valeur est affichée, utilisez les format-number(<value>, '#.##') format. Cela devrait garantir que nombre entier ou décimal de l'affichage de valeurs comme initialement présents dans le XML.
  3. Pour les balises facultatives (comme la "Réduction"), utilisez la format-number(<value>, '0.00') fonction, même si la valeur est calculée. Cela est nécessaire parce que si la balise est absent, en essayant d'obtenir une valeur donnera une NaN résultat.

Ici est un exemple illustratif de la transformation XSLT:

  <x:stylesheet version="1.0" xmlns:x="http://www.w3.org/1999/XSL/Transform">
  <x:template match="/">
    <html>
      <body>
        <table border="1" width="60%">
          <tr>
            <th>Simple</th>
            <th>number()</th>
            <th>format-number(&lt;expression&gt;, '0.00')</th>
            <th>format-number(&lt;expression&gt;, '#.##')</th>
          </tr>
          <x:apply-templates />
        </table>
      </body>
    </html>
  </x:template>

  <x:template match="Item">
    <x:variable name="qty" select="number(@numItems)" />
    <x:variable name="cost" select="number(ItemCost) * $qty" />
    <x:variable name="extraCharges" select="(number(Tax) + number(TxnFee)) * $qty"/>
    <x:variable name="discount" select="format-number(Discount, '0.00') * $qty"/>
    <tr>
      <td>
      <!-- Works for Integer-XML, but values in Decimal-XML are
      *sometimes* rendered upto 14 decimal places. Even though Quickwatch
      shows it correctly in the debugger in VS. I cannot figure out what's
      special about the error cases. -->
        <x:value-of select="$cost + $extraCharges - $discount"/>
      </td>
      <td>
        <!-- Works same as the above case. -->
        <x:value-of select="number($cost + $extraCharges - $discount)"/>
      </td>
      <td>
      <!-- Works for Decimal-XML, but values in Integer-XML are always
      rendered with decimal digits. -->
        <x:value-of select="format-number(($cost + $extraCharges - $discount), '0.00')"/>
      </td>
      <td>
      <!-- Works for Integer-XML, but some values in Decimal-XML are
      rendered incorrectly. For example, 95.20 is rendered as 95.2;
      95.00 is rendered as 95 -->
        <x:value-of select="format-number(($cost + $extraCharges - $discount), '#.##')"/>
      </td>
    </tr>
  </x:template>
</x:stylesheet>

Que les commentaires HTML remarque, il fonctionne dans la plupart des cas, mais pas tous.

Je voudrais utiliser une expression unique de formater tous les prix de même que l'entrée, plutôt que d'appliquer "lorsque-dans le cas contraire" des constructions partout, ce qui serait en outre exiger un booléen en paramètre passé à la transformation XSLT pour déterminer le format d'affichage. L'état actuel de la transformation XSLT est que tous les nombres sont arrondis, quelle que soit l'entrée, à l'aide format-number(<expression>, '0').

Comment puis-je y arriver?


Edit: Après Dimitre commentaire, j'ai décidé de créer un exemple de XML et XSLT-dessus), de sorte que les experts peuvent essayer facilement.

XML exemple (celui-ci contient des décimales):

<ShoppingList>
  <Item numItems="2">
    <ItemCost>10.99</ItemCost>
    <Tax>3.99</Tax>
    <TxnFee>2.99</TxnFee>
    <Discount>2.99</Discount>
  </Item>
  <Item numItems="4">
    <ItemCost>15.50</ItemCost>
    <Tax>5.50</Tax>
    <TxnFee>3.50</TxnFee>
    <Discount>3.50</Discount>
  </Item>
</ShoppingList>
  • Vous avez oublié d'indiquer, même la plus simple possible document XML. Ce n'est pas utile.
  • Je n'ai pas oublié de le fournir, mais je dois avouer que je ne savais pas qu'une source XML serait nécessaire parce que ce n'est pas vraiment une transformation de la question. C'est une question générique décimal mise en forme. Encore, je vais essayer d'en créer un si cela aide.
InformationsquelleAutor Cerebrus | 2009-03-21