入力 XML に小数が含まれているかどうかに応じて、XSLT ファイルが条件付きで小数とともに価格を表示する必要がある状況があります。したがって、2 種類の値を持つ XML ファイルを受け取ることができます。XML には、2 桁までの小数点以下でフォーマットされたすべての価格が含まれます (これを「Decimal-XML」と呼びます)。または、価格は最も近い整数に丸められます (これを「10 進 XML」と呼びます)。 1 つの「Integer-XML」)。
私の問題は、XSLT ファイルのリファクタリングを最小限に抑えながら、XML 入力と同じ形式で XHTML への変換を適用できるようにする必要があることです。これを達成するために、私は次の 3 つのガイドラインを実装し、チームに提案しました。
format-number()
値が計算のために計算されているとき、または変数に格納されているときに、すべての関数呼び出しを削除します。number(<value>)
代わりに使用してください。ただし、このルールには特定の条件が適用されます (以下を参照)。- 値を表示する場合は、
format-number(<value>, '#.##')
フォーマットを使用してください。これにより、整数値または 10 進数値が XML に元々存在していたとおりに表示されるようになります。 - オプションのタグ (「Discount」など) の
format-number(<value>, '0.00')
場合は、値が計算されるだけの場合でも関数を使用します。タグが存在しない場合、値を取得しようとすると結果が得られるため、これが必要ですNaN
。
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>
HTML コメントにあるように、ほとんどの場合に機能しますが、すべてではありません。
表示形式を決定するために XSLT に渡されるブール値パラメーターを追加で必要とする "when-otherwise" 構造をあらゆる場所に適用するのではなく、単一の式を使用してすべての価格を入力と同じようにフォーマットしたいと考えています。XSLT の現在の状態は、入力に関係なくすべての数値が を使用して四捨五入されることformat-number(<expression>, '0')
です。
どうすればこれを達成できますか?
編集: Dimitre のコメントの後、専門家が簡単に試すことができるように、サンプル XML (および上記の XSLT) を作成することにしました。
サンプル XML (これには小数が含まれています):
<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>