Ich habe eine Situation, wo meine XSLT-Dateien Preise mit Dezimalzahlen bedingt anzeigen sollten, abhängig davon, ob die XML-Eingabe Dezimalzahlen enthält oder nicht. So kann ich XML-Dateien mit zwei Arten von Werten empfangen - XML wird alle Preise enthalten, die mit Dezimalen bis zu zwei Stellen formatiert sind (ich nenne dies "Dezimal-XML") oder die Preise werden auf die nächste Ganzzahl gerundet (ich nenne das) ein "Integer-XML").XSLT Dezimale Formatierung basierend auf Eingabe XML
Mein Problem ist, dass ich so wenig wie möglich in den XSLT-Dateien umgestalten und ihnen dennoch erlauben soll, die Transformation auf XHTML im selben Format wie die XML-Eingabe anzuwenden. Um dies zu erreichen, habe ich umgesetzt und schlug vor, drei Richtlinien an meinem Team:
- Alle entfernen
format-number()
Funktion aufruft, wenn der Wert in einer Variablen für Berechnungen oder gespeichert berechnet wird. Verwenden Sie stattdessennumber(<value>)
. Für diese Regel gelten jedoch bestimmte Bedingungen (siehe unten). Wenn der Wert angezeigt werden soll, verwenden Sie das Formatformat-number(<value>, '#.##')
. Dies sollte sicherstellen, dass Integer- oder Dezimalwerte so angezeigt werden, wie sie ursprünglich im XML vorhanden waren. - Verwenden Sie für optionale Tags (z. B. "Rabatt") die Funktion
format-number(<value>, '0.00')
, auch wenn der Wert nur berechnet wird. Dies ist notwendig, da, wenn das Tag nicht vorhanden ist, der Versuch, einen Wert zu erhalten, einNaN
Ergebnis ergibt. Hier
ist ein anschauliches Beispiel für die 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(<expression>, '0.00')</th>
<th>format-number(<expression>, '#.##')</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>
Als HTML-Kommentare Note, es funktioniert in den meisten Fällen aber nicht alle.
Ich würde gerne einen einzelnen Ausdruck verwenden, um alle Preise gleich wie die Eingabe zu formatieren, anstatt "wann-sonst" -Konstrukte überall anzuwenden, die zusätzlich einen booleschen Parameter benötigen, der an das XSLT übergeben wird, um das Anzeigeformat zu bestimmen. Der aktuelle Status von XSLT besteht darin, dass alle Zahlen unabhängig von der Eingabe mit format-number(<expression>, '0')
gerundet werden.
Wie bewerkstellige ich das?
Edit: Nach Dimitre Kommentar, habe ich beschlossen, eine Probe XML (und die XSLT oben) zu schaffen, damit die Experten kann es leicht ausprobieren.
XML-Beispiel (Diese enthält Dezimalstellen):
<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>
Sie haben vergessen, selbst das einfachste XML-Dokument anzugeben. Dies ist nicht hilfreich. –
@Dimitre: Ich habe nicht vergessen, es zu geben, aber ich muss zugeben, dass ich nicht erkannte, dass eine XML-Quelle erforderlich wäre, weil dies nicht wirklich eine Frage der Transformation ist. Es ist eine allgemeine Frage zur dezimalen Formatierung. Trotzdem werde ich versuchen, eine zu erstellen, wenn das hilft. – Cerebrus