简体   繁体   中英

XSLT: How to use format-number and decimal-format?

I know such questions have been asked before but I still don't get it.

I am using .NET for XSL transformations.

MSDN describes format-number as:

Converts numbers into strings. The conversion is the result of formatting the number specified in the first argument (number), using the format specified in the second argument (string), and applying the rules defined in the decimal format named in the third optional argument (string). If the third argument, the decimal format name, is omitted, the default decimal format is used. This function and the element are designed to be used together.

Example

Given the following XML I want to set up a XSLT that exposes the decimals as european notaton ('.' as decimal separator and ',' as group separator) and in english (or standard notation).

data.xml:

<?xml version="1.0" encoding="utf-8" ?>
<Model>
  <Decimal value="1.256"/>
  <Decimal value="19099.33345"/>
</Model>

I use a XSLT document that declares both decimal formats and uses them in the select-statement, one time in order to output in european and one time to output in english notation:

trafo.xslt

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
>
    <xsl:decimal-format name="european" decimal-separator=',' grouping-separator='.' />
    <xsl:decimal-format name="en" decimal-separator='.' grouping-separator=',' />

  <xsl:template match="/Model">

      <xsl:for-each select="Decimal">
        Auf european: <xsl:value-of select="format-number(@value, '###.###,00', 'european')"/>
        <!--Auf englisch: <xsl:value-of select="format-number(@value, '###.###,00', 'en')"/>-->
      </xsl:for-each>

      </xsl:template>
</xsl:stylesheet>

My expectation is that the transformation will output something like:

european: 1,256
english: 1.256
european: 19.099,33345
english: 19,099.33345

But instead I get the exception also mentioned here :

"Format '#,###.00' cannot have zero digit symbol after digit symbol after decimal point."

So when I need to change the format pattern for english and european notations what is the purpose of decimal-format at all?

For completeness, here is the C# code I used for the transformation

        XDocument data = XDocument.Load("data.xml");
        XDocument xslt = XDocument.Load("trafo.xslt");

        XslCompiledTransform compiled = new XslCompiledTransform();
        using (var reader = xslt.CreateReader())
        {
            compiled.Load(reader);
        }

        // wir wollen auch Fragmente zulassen
        var writerSettings = new XmlWriterSettings { ConformanceLevel = ConformanceLevel.Auto };
        var readerSettings = new XmlReaderSettings { ConformanceLevel = ConformanceLevel.Auto };
        var stringReader = new StringReader(data.ToString());
        var details = new StringBuilder();
        using (var reader = XmlReader.Create(stringReader, readerSettings))
        {
            using (var writer = XmlWriter.Create(details, writerSettings))
            {
                compiled.Transform(reader, writer);
            }
        }

        Console.WriteLine(details.ToString());

Decimal pattern (the 3rd argument of format-number ) says which chars serve as both separators.

The first instruction format-number(@value, '###.###,00', 'european')"/ looks OK, since european decimal-format has decimal-separator set to just a comma.

But the second instruction format-number(@value, '###.###,00', 'en') causes an error, because:

  • en decimal-format has decimal-separator set to a dot ,
  • you specified in this place a comma .

Change the second instruction to format-number(@value, '###,###.00', 'en') (note both separators changed).

Maybe it would be more understandable if the error message had been formulated this way:

  • After you "pass" the char separating integer part from fractional one (in european - a comma, in English - a dot),
  • it is not allowed to have a # char (ddigit placeholder, can be changed to a space),
  • and after it a '0' char (zero digit placeholder).

In your (English) example you have actually:

  • 3 places (digit symbols) for integer part,
  • a decimal point (a dot - English version),
  • another 3 places (also digit symbols) for fractional part, till now all digits can be changed to spaces,
  • a grouping separator (a comma),
  • another 2 digit places ( zero digit symbols), and this is the cause of the error message.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM