Главная » XSLT » Форматирование чисел

0

Задача

Требуется выводить числа в разных форматах.

Решение

У этой задачи есть два общих решения.

Использование xsl:decimal-format в сочетании с format-number()

Элемент верхнего уровня xsl:decimal-format задает именованное прави­ло форматирования, на которое можно ссылаться при вызове функции format- number(). У элемента xsl:decimal-format много атрибутов, описывающих правила форматирования. В таблице 3.1 описываются все атрибуты, и в скобках для каждого приведено значение по умолчанию.

Таблица 3.1. Атрибуты элемента xsl:decimal-format

Атрибут

Назначение

name

Необязательное имя правила. Если этот атрибут

 

отсутствует, то правило принимается по умолчанию.

 

Может существовать лишь одно правило по умолчанию,

 

и все имена должны быть уникальны (даже в случае

 

импорта, когда действует система приоритетов).

decimal-separator (.

) Символ, отделяющий целую часть от дробной.

grouping-separator (,

) Символ, разделяющий группы цифр.

infinity (Infinity)

Строка, представляющая бесконечность.

minus-sign (-)

Символ, представляющий знак минуса.

NaN (Nan)

Строка, представляющая значение «не число».

percent (%)

Знак процента.

per-mille (fc)

Знак промилле.

zero-digit (0)

Символ, используемый в форматной строке, чтобы показать,

 

где должны находиться начальные или конечные нули.

 

Задание этого символа меняет основание системы счисления.

 

См. пример 3.1.

1 Реализации EXSLT приведены в том виде, в котором они существовали на момент написания этой книги. Естественно, со временем они могут быть улучшены или отвергну­ты по мере выхода в свет новых версий XPath и XSLT.

Атрибут

Назначение

digit (#)

Символ, используемый в форматной строке, чтобы показать,

 

где должны находиться значащие цифры.

pattern-separator (;

) Символ, используемый в форматной строке для разделения

 

положительной и отрицательной подмасок.

В таблице 3.2 описаны аргументы функции format-number().

Таблица 3.2. Аргументы функции format-number()

Аргумент

Назначение

value

Форматируемое значение.

format

Форматная строка (например, #,###.00).

name (необязательный)

Имя элемента xsl:decimal-format.

Использование xsl:number

Элемент xsl:number обычно применяется для нумерации узлов по порядку, но годится и для форматирования чисел. Атрибуты, используемые в этом случае, описаны в таблице 3.3.

Таблица 3.3. Атрибуты элемента xsl:number

В таблице 3.4 показаны, как интерпретируются спецификаторы формата, за­данные в форматной строке.

Таблица 3.4. Примеры применения спецификаторов формата

Таблица 3.4. Примеры применения спецификаторов формата (окончание)

Форматная строка представляет собой последовательность спецификаторов формата и знаков пунктуации. Указывать несколько спецификаторов имеет смысл только тогда, когда форматируемое значение содержит несколько чисел.

Обсуждение

С помощью описанного выше механизма можно решить почти любую задачу форматирования чисел.

для вывода в несколько колонок с фиксированным числом десятичных знаков

Мы дополним число начальными и конечными нулями, а потом заменим на­чальные нули пробелами и добавим в конце знак «минус». В результате получит­ся аккуратная таблица с несколькими колонками, выровненными по правому краю, при условии, что для ее вывода на устройство применяется моноширинный шрифт. В примерах 3.1 – 3.3 показаны более привычные способы заполнения. В них иллюстрируется поведение спецификатора форматирования 0.

Пример 3.1. Входные данные

<numbers>

<number>10</number> <number>3.5</number> <number>4.4 4</number> <number>7 7.7 77 7</number> <number>-8</number> <number>1</number> <number>4 4 4</number> <number>1.12 34</number> <number>7.77</number> <number>3.1415 927</number> <number>10</number> <number>9</number> <number>8</number> <number>7</number> <number>6 6 6</number> <number>5 555</number> <number>-4 4 4 4 4 4 4</number>

<number>2 2.3 3</number> <number>18</number> <number>3 6.5 4</number> <number>4 3</number> <number>9 9 9 9 9</number> <number>9 9 9 9 9 9</number> <number>9 9 9 9 9 9 9</number> <number>32</number> <number>6 4</number> <number>-64.0 0 01</number> </numbers>

Пример 3.2. format-numbers-into-columns.xslt

<xsl:stylesheet version="1.0" xmlns:xsl="http://www,w3.org/1999/XSL/Transform"> <xsl:output method="text" />

<xsl:variable name="numCols" select="4"/>

<xsl:template match="numbers">

<xsl:for-each select="number[position() mod $numCols = 1]"> <xsl:apply-templates

select=". | following-sibling::number[position() &lt; $numCols]" mode="format"/> <xsl:text>&#xa;</xsl:text> </xsl:for-each> </xsl:template>

<xsl:template match="number" name="format" mode="format"> <xsl:param name="number" select="." /> <xsl:call-template name="leading-zero-to-space"> <xsl:with-param name="input"

select="format-number($number,

‘0000000.0000 ; 0000000.0000- ‘)"/>

</xsl:call-template> </xsl:template>

<xsl:template name="leading-zero-to-space"> <xsl:param name="input"/> <xsl:choose>

<xsl:when test="starts-with($input,’0′)"> <xsl:value-of select="”"/>

<xsl:call-template name="leading-zero-to-space">

<xsl:with-param name="input" select="substring-after($input,’0′)"/>

</xsl:call-template>

</xsl:when>

<xsl:otherwise>

<xsl:value-of select="$input"/> </xsl:otherwise> </xsl:choose> </xsl:template>

</xsl:stylesheet>

Пример 3.3. Вывод

10.00                     3.50                4.40

77.77                    -8.00                1.00

444.00                     1.12               7.77

3.14                    10.00                 9.00

8.00                     7.00               666.00

5555.00              -4444444.00             22.33

18.00                  36.5400               43.00

99999.00  999999.00 9999999.00

32.00                    64.00              -64.00

Форматирование денежных сумм, как принято в США

Пример 3.4. Бухгалтерский формат

<xsl:template match="number" name="format" mode="format"> <xsl:param name="number" select="." /> <xsl:text> $ </xsl:text>

<xsl:call-template name="leading-zero-to-space"> <xsl:with-param name="input"

select="format-number($number,

‘ 0000000.00 ;(0000000.00)’)"/>

</xsl:call-template> </xsl:template>

Вывод:

$ 10.00 $            3.50 $         4.44

$ 77.78 $          (8.00) $         1.00

$ 444.00                $ 1.12         $       7.77

$ 3.14  $           10.00 $         9.00

$ 8.00  $            7.00 $       666.00

$ 5555.00               $ (4444444.00) $       22.33

$ 18.00 $           36.54 $        43.00

$ 99999.00              $ 999999.00    $ 9999999.00

$ 32.00 $           64.00 $       (64.00)

, принятое во многих европейских странах

В примере 3.5 демонстрируется использование именованного формата. Пример 3.5. по-европейски

<xsl:stylesheet version="1.0"

xmlns:xsl="http://www.w3.org/1999/XSL/Transform"

xmlns:str="http://www.ora.com/XSLTCookbook/namespaces/strings"> <xsl:output method="text" /> <!– Из рецепта 2.5 –>

<xsl:include href="../strings/str.dup.xslt"/> <xsl:variable name="numCols" select="3"/>

<xsl:decimal-format name="WesternEurope"

decimal-separator=M," grouping-separator="."/>

<xsl:template match="numbers">

<xsl:for-each select="number[position() mod $numCols = 1]"> <xsl:apply-templates

select=". | following-sibling::number[position() &lt; $numCols]" mode="format"/> <xsl:text>&#xa;</xsl:text> </xsl:for-each> </xsl:template>

<xsl:template match="number" name="format" mode="format"> <xsl:param name="number" select="." /> <xsl:call-template name="pad"> <xsl:with-param name="string"

select—’format-number($number,’#.###,00′,’WesternEurope’)"/> </xsl:call-template> </xsl:template>

<xsl:template name="pad"> <xsl:param name="string"/> <xsl:param name="width" select="16"/> <xsl:call-template name="str:dup">

<xsl:with-param name="input" select="”"/>

<xsl:with-param name="count" select="$width – string-length($string)"/> </xsl:call-template> <xsl:value-of select="$string"/> </xsl:template>

</xsl:stylesheet>

Вывод:

10,00                   3,50                  4,44

77,78                  -8,00                  1,00

444,00               1,12                7,77

3,14                  10,00                   9,00

8,00                   7,00                 666,00

5.555,00       -4.444.444,00               22,33

18,00                 36,54                  43,00

99.999,00 999.999,00 9.999.999,00

32,00                  64,00               -64,00

Запись числа римскими цифрами

В примере 3.6 элемент xsl:number применяется для нумерации строк и ко­лонок римскими цифрами.

Пример 3.6. Нумерация римскими цифрами

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:str="http://www.ora.com/XSLTCookbook/namespaces/strings" > <xsl:output method="text" />

<xsl:include href="../strings/str.dup.xslt" />

<xsl:variable name="numCols" select="3"/>

<xsl:template match="numbers">

<xsl:for-each select="number[position() &lt; = $numCols]"> <xsl:text>        </xsl:text>

<xsl:number value="position()" format="I"/><xsl:text> </xsl:text> </xsl:for-each>

<xsl:text>&#xa;      </xsl:text>

<xsl:for-each select="number[position() &lt; = $numCols]">

<xsl:text>——— </xsl:text>

</xsl:for-each>

<xsl:text>&#xa;</xsl:text> <xsl:for-each select="number[position() mod $numCols = 1]"> <xsl:call-template name="pad"> <xsl:with-param name="string">

<xsl:number value="position()" format="i"/> </xsl:with-param>

<xsl:with-param name="width" select="4"/> </xsl:call-template>|<xsl:text/> <!– см. рецепт 7.1 —> <xsl:apply-templates

select=". | following-sibling::number[position() &lt; $numCols]"

mode="format"/> <xsl:text>&#xa;</xsl:text> </xsl:for-each> </xsl:template>

<xsl:template match="number" name="format" mode="format"> <xsl:param name="number" select="." /> <xsl:call-template name="pad">

<xsl:with-param name="string" select="format-number(.,’#,###.00′)"/> </xsl:call-template> </xsl:template>

<xsl:template name="pad"> <xsl:param name="string"/> <xsl:param name="width" select="16"/> <xsl:call-template name="str:dup">

<xsl:with-param name="input" select="”"/>

<xsl:with-param name="count" select="$width – string-length($string)"/> </xsl:call-template> <xsl:value-of select="$string"/> </xsl:template>

</xsl:stylesheet>

Вывод:

Нумерация колонок, как в электронной таблице

В электронных таблицах колонки обозначаются буквами A, B, C, … ZZ, и мы можем сделать то же самое с помощью элемента xsl:number (пример 3.7).

Пример 3.7. Нумерация колонок, как в электронной таблице

<xsl:template match="numbers">

<xsl:for-each select="number[position() &lt;= $numCols]"> <xsl:text> </xsl:text>

<xsl:number value="position()" format="A"/><xsl:text> </xsl:text>

<xsl:text>    </xsl:text>

</xsl:for-each>

<xsl:text>&#xa;</xsl:text> <xsl:for-each select="number[position() &lt; = $numCols]">

<xsl:text> ——–  </xsl:text>

</xsl:for-each>

<xsl:text>&#xa;</xsl:text> <xsl:for-each select="number[position() mod $numCols = 1]"> <xsl:value-of select="position()"/><xsl:text>|</xsl:text> <xsl:apply-templates

select=". | following-sibling::number[position() &lt; $numCols]" mode="format"/> <xsl:text>&#xa;</xsl:text> </xsl:for-each> </xsl:template>

<xsl:template match="number" name="format" mode="format"> <xsl:param name="number" select="." /> <xsl:call-template name="pad">

<xsl:with-param name="string" select="format-number(.,’#,###.00′)"/> </xsl:call-template> <xsl:text> </xsl:text> </xsl:template>

Вывод:

Запись чисел арабскими цифрами

Записать числа цифрами, используемыми в других языках, можно, задав в ка­честве атрибута zero-digit в элементе xsl:decimal-format обозначение нуля в соответствующем языке. В примере ниже мы взяли символ Unicode с ко­дом 0x660 (нуль в арабской нотации).

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:str="http://www.ora.com/XSLTCookbook/namespaces/strings">

<xsl:output method="text" encoding="UTF-8"/>

<xsl:include href="../strings/str.dup.xslt"/>

<!– Здесь говорится, что нуль находится в кодовой позиции 0x660, следовательно, 1 занимает кодовую позицию 0x661 и т.д. –> <xsl:decimal-format name="Arabic" zero-digit="&#x660;"/>

<xsl:template match="numbers"> <xsl:for-each select="number">

<xsl:call-template name="pad">

<xsl:with-param name="string" select="format- number(.,’#,###.00′)"/>

</xsl:call-template> = <xsl:text/> <xsl:value-of select="format- number(.,’#,###.S#x660;S#x660;,,’Arabic,)"/> <xsl:text>&#xa;</xsl:text> </xsl:for-each> </xsl:template>

<xsl:template name="pad"> <xsl:param name="string"/> <xsl:param name="width" select="16"/> <xsl:value-of select="$string"/> <xsl:call-template name="str:dup">

<xsl:with-param name="input" select="”"/> <xsl:with-param name="count" select="$width – string- length($string)"/>

</xsl:call-template> </xsl:template>

</xsl:stylesheet>

Этот код выводит следующий результат:

Мангано Сэл  XSLT. Сборник рецептов. – М.: ДМК Пресс, СПБ.: БХВ-Петербург, 2008. – 864 с.: ил.

По теме:

  • Комментарии