При использовании цифровых форматов нумерации (иными словами, токенов вида 1, 01, 001 и так далее) цифры в номере можно разделить на группы, получив, например, такие номера как "2.00.00" из 20000 или "0-0-0-2" из 2. Для этой цели в xsclass="underline" number используется пара атрибутов grouping-separator и grouping-size.
Атрибут grouping-separator задает символ, который следует использовать для разбивки номера на группы цифр, в то время как grouping-size указывает размер группы. Эти атрибуты всегда должны быть вместе — если хотя бы один из них опущен, второй просто игнорируется.
Элемент xsclass="underline" number вида
<xsclass="underline" number
format="[00000001]"
grouping-separator="."
grouping-size="2"/>
будет генерировать номера в следующей последовательности:
1 → '[00.00.00.01]'
2 → '[00.00.00.02]'
...
999 → '[00.00.09.99]'
1000 → '[00.00.10.00]'
Пожалуй, следует упомянуть, что в значениях атрибутов format, lang, letter-value, grouping-size и grouping-separator могут быть указаны шаблоны значений, иными словами могут использоваться выражения в фигурных скобках. Это может быть полезно, например, для того, чтобы сгенерировать форматирующие токены во время выполнения преобразования.
В следующем шаблоне формат номера секции зависит от значения атрибута format ее родительского узла:
<xsclass="underline" template match="section">
<xsclass="underline" number
format="{../@format}-1 "
level="multiple"
count="chapter|section"/>
<xsclass="underline" value-of select="@title"/>
</xsclass="underline" template>
При обработке входящего документа
<doc>
<chapter format="I" title="First Chapter">
<section title="First Section"/>
<section title="Second Section"/>
<section title="Third Section"/>
</chapter>
</doc>
нумерация секций будет выглядеть как
I-1 First Section
I-2 Second Section
I-3 Third Section
Если же атрибут format элемента chapter будет иметь значение 1, секции будут пронумерованы в виде
1-1 First Section
1-2 Second Section
1-3 Third Section
Форматирование чисел
Мы уже познакомились с функцией языка XPath string, которая конвертирует свой аргумент в строку. Эта функция может преобразовать в строку и численное значение, но возможности ее при этом сильно ограничены.
К счастью, XSLT предоставляет мощные возможности для форматирования строкового представления чисел при помощи функции format-number и элемента xsclass="underline" decimal-format.
Функция format-number
Запись функции имеет следующий вид:
string format-number(number, string, string?)
Функция format-number принимает на вход три параметра. Первым параметром является число, которое необходимо преобразовать в строку, применив при этом форматирование. Вторым параметром является образец, в соответствии с которым будет форматироваться число. Третий параметр указывает название десятичного формата, который следует применять.
Образец форматирования в XSLT определяется точно так же, как в классе DecimalFormat языка Java. Для того чтобы читателю, не знакомому с Java, не пришлось изучать документацию этого языка, мы приведем полный синтаксис образцов форматирования. Продукции образца форматирования мы будем помечать номерами с префиксом NF, чтобы не путать их с другими продукциями.
Прежде всего, образец форматирования может состоять из двух частей: первая часть определяет форматирование положительного числа, вторая часть — отрицательного. Запишем это в виде EBNF-продукции:
[NF 1] NFPattern ::= NFSubpattern (NFSubpatternDelim NFSubpattern)?
Двум частям образца форматирования соответствуют нетерминалы NFSubpattern, которые разделены нетерминалом NFSubpatternDelim.
В случае если вторая часть образца форматирования опушена, отрицательные числа форматируются точно так же, как и положительные, но им предшествует префикс отрицательного числа (по умолчанию — знак "минус", "-").
format-number(1234.567,'#.00;negative #.00') → '1234.57'
format-number(-1234.567,'#.00/negative #.00') → 'negative 1234.57'
format-number(-1234.567,'#.00') → '-1234.57'
Каждая из частей образца форматирования состоит из префикса (NFPrefix), целой части (NFInteger), необязательной дробной части (NFFractional) и суффикса (NFSuffix).
[NF 2] NFSubpattern ::= NFPrefix NFinteger NFFractional? NFSuffix
Префикс или суффикс образца форматирования могут содержать символ процента. Если суффикс содержит символ процента, число должно быть умножено на 100 и выведено со знаком процента. Наличие символа процента в префиксе на форматирование не влияет.
format-number(0.45,'0.00%') → '45.00%'
format-number(0.45,'0.##%') → '45.00%'
format-number(0.45678,'%0.00') → '%0.46'
format-number(0.45678,'0.####%') → '45.678%'
Префикс задает строку, которая будет предшествовать числу, это может быть последовательность любых неформатирующих символов (NFChar) плюс символ процента (NFPercent). Аналогично, суффикс будет следовать за числом, и он тоже не может содержать форматирующих символов (за исключением символа процента).
[NF 3] NFPrefix ::= (NFChar NFPercent?)*
[NF 4] NFSuffix ::= (NFChar NFPercent?)*
Если мы хотим заключить наше число, к примеру, в квадратные скобки, мы должны будем включить в его образец форматирования префикс "[" и суффикс "]":
format-number(123456, '[#]') → '[123456]'