7 Создание конечного дерева

В этой главе описываются инструкции, непосредственно создающие узлы в конечном дереве.

7.1 Создание элементов и атрибутов

7.1.1 Фиксированные конечные элементы

В шаблоне элемент из стиля, который не принадлежит пространству имен XSLT и не является элементом расширения (см. [14.1 Элементы расширения]), обрабатывается, чтобы создать узел элемента с тем же расширенным именем. Содержимое этого элемента является шаблоном, который обрабатывается чтобы получить содержимое для созданного узла элемента. Узел созданного элемента будет иметь те узлы атрибутов, которые были представлены в дереве стиля в узле данного элемента, а не атрибутов с названиями из пространства имен XSLT.

Созданный узел элемента будет также иметь копию узлов для пространства имен, которые присутствовали в узле элемента в дереве стиля, за исключением тех узлов пространства имен, чьим строковым значением является URI пространства имен XSLT (http://www.w3.org/1999/XSL/Transform), URI пространства имен, декларированного как пространство расширения (см. [14.1 Элементы расширения]), или URI пространства имен, обозначенного как исключенное. URI пространства имен обозначается как исключенное с помощью атрибута exclude-result-prefixes в элементе xsl:stylesheet или атрибута xsl:exclude-result-prefixes в фиксированном конечном элементе. Значением обоих этих атрибутов является перечень префиксов пространства имен, разделенных пробельным символом. Пространство имен, связанное с каждым из этих префиксов, обозначается как исключенное. Если с префиксом элемента, имеющего атрибут exclude-result-prefixes или xsl:exclude-result-prefixes, не связано никакого пространства имен, фиксируется ошибка. Пространство имен по умолчанию, декларированное с помощью xmlns, может быть обозначено как исключенное если в соответствующий список префиксов пространства имен включить #default. Объявление пространства имен в качестве исключенного действует в том поддереве стиля, которое начинается с элемента, имеющего данный атрибут exclude-result-prefixes или xsl:exclude-result-prefixes. Поддерево, начинающееся с элемента xsl:stylesheet, не включает стили, импортированные или включенные непосредственным потомком этого элемента xsl:stylesheet.

Замечание: Если стиль использует декларацию пространства имен только для адресации в исходном дереве, то указание этого префикса в атрибуте exclude-result-prefixes позволит избежать появления в конечном дереве ненужных деклараций пространства имен.

Значение атрибута в фиксированном конечном элементе интерпретируется как шаблон значения атрибута: он может содержать выражения, заключенные в фигурные скобки ({}).

URI пространства имен в дереве стиля, которое используется для определения URI пространства имен в конечном дереве, называется фиксированным URI пространства имен. Это относится к:

<!-- Category: top-level-element -->
<xsl:namespace-alias
  stylesheet-prefix = prefix | "#default"
  result-prefix = prefix | "#default" />

Чтобы декларировать, что один URI пространства имен является синонимом другого URI пространства имен, в стиле может использоваться элемент xsl:namespace-alias. Если фиксированный URI пространства имен был декларирован как синоним другого URI пространства имен, то в конечном дереве URI пространства имен будет представлен не этим фиксированным URI пространства имен, а тем URI пространства имен, для которого он является синонимом. Элемент xsl:namespace-alias декларирует, что URI пространства имен, связанный с префиксом, задаваемым атрибутом stylesheet-prefix, является синонимом для URI пространства имен, связанного с префиксом, задаваемым атрибутом result-prefix. Таким образом, атрибут stylesheet-prefix указывает URI пространства имен, который будет представлен в стиле, а атрибут result-prefix задает соответствующий URI пространства имен, который будет представлен в конечном дереве. Пространство имен по умолчанию (декларируемое с помощью xmlns) может быть задано не префиксом, а с помощью #default. Если некое URI пространства имен декларировано как синоним сразу для нескольких различных URI пространства имен, то используется декларация с наивысшим приоритетом импорта. Если и таких деклараций будет несколько, фиксируется ошибка. XSLT процессор может сигнализировать об этой ошибке, если он этого не делает, то должен обработать ошибку сам, выбрав среди деклараций с наивысшим приоритетом импорта ту, которая в стиле появилась последней.

Если фиксированные конечные элементы используются для создания узлов элементов, атрибутов или пространств имен, использующих URI пространства имен XSLT, такой стиль должен использовать синоним. Например, стиль

<xsl:stylesheet
  version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:fo="http://www.w3.org/1999/XSL/Format"
  xmlns:axsl="http://www.w3.org/1999/XSL/TransformAlias">

<xsl:namespace-alias stylesheet-prefix="axsl" result-prefix="xsl"/>
 <xsl:template match="/">
  <axsl:stylesheet>
    <xsl:apply-templates/>
  </axsl:stylesheet>
</xsl:template>
 <xsl:template match="block">
  <axsl:template match="{.}">
     <fo:block><axsl:apply-templates/></fo:block>
  </axsl:template>
</xsl:template>

</xsl:stylesheet>

будет генерировать стиль XSLT из документа следующего вида:

<elements>
<block>p</block>
<block>h1</block>
<block>h2</block>
<block>h3</block>
<block>h4</block>
</elements>
Замечание: Синонимы могут также понадобиться для иных пространств имен, нежели URI пространства имен XSLT. Например, фиксированные конечные элементы, принадлежащие пространству имен, работающему с цифровыми подписями, могут привести к тому, что стили XSLT будут неправильно обрабатываться программами обеспечения безопасности общего назначения. Используя синоним для этого пространства имен, такую нестыковку можно устранить.

7.1.2 Создание элементов с помощью xsl:element

<!-- Category: instruction -->
<xsl:element
  name = { qname }
  namespace = { uri-reference }
  use-attribute-sets = qnames>
  <!-- Content: template -->
</xsl:element>

Элемент xsl:element позволяет создавать элемент с вычисляемым названием. Расширенное имя создаваемого элемента определяется обязательным атрибутом name и необязательным атрибутом namespace. Содержимое элемента xsl:element является шаблоном для атрибутов и непосредственного потомка создаваемого элемента.

Атрибут name интерпретируется как шаблон значения атрибута. Если строка, получающаяся после обработки шаблона значения атрибута, не является QName, фиксируется ошибка. XSLT процессор может сигнализировать об этой ошибке, если он этого не делает, то должен обработать ошибку сам, представив результат обработки элемента xsl:element последовательностью узлов, созданных обработкой содержимого элемента xsl:element и исключением всех исходных узлов атрибутов. Если атрибут namespace не был предоставлен, QName приводится к расширенному имени с помощью деклараций пространства имен, в области действия которых находится данный элемент xsl:element, включая все декларации пространства имен по умолчанию.

Если атрибут namespace присутствует, также обрабатывается как шаблон значения атрибута. Строка, полученная после обработки шаблона значения атрибута, должна являться ссылкой URI. Если эта строка не будет синтаксически правильной ссылкой URI, ошибка фиксироваться не будет. Если строка пустая, то расширенное имя данного элемента имеет нулевой URI пространство имен. В противном случае, эта строка используется как URI пространства имен для расширенного имени создаваемого элемента. Локальная часть QName, задаваемая атрибутом name, используется как локальная часть в расширенном имени создаваемого элемента.

При отборе префикса для вывода созданного элемента в виде XML XSLT процессоры могут воспользоваться префиксом QName, задаваемым атрибутом name, однако они вовсе не обязаны поступать именно так.

7.1.3 Создание атрибутов с помощью xsl:attribute

<!-- Category: instruction -->
<xsl:attribute
  name = { qname }
  namespace = { uri-reference }>
  <!-- Content: template -->
</xsl:attribute>

Чтобы к конечным элементам добавить атрибуты, можно использовать элемент xsl:attribute независимо от того, созданы ли первые фиксированными конечными элементами или такими инструкциями, как xsl:element. Расширенное имя для создаваемого атрибута задается обязательным атрибутом name и необязательным атрибутом namespace. Обработка элемента xsl:attribute добавляет к узлу, содержащему конечный элемент, узел атрибута. Содержимое элемента xsl:attribute является шаблоном для значения создаваемого атрибута.

Атрибут name интерпретируется как шаблон значения атрибута. Если строка, возникающая после обработки шаблона значения атрибута, не является QName и не является строкой xmlns, фиксируется ошибка. XSLT процессор может сигнализировать об этой ошибке. Если он этого не делает, то должен сам обработать ошибку, просто не добавляя в конечное дерево этот атрибут. Если атрибут namespace отсутствует, QName приводится к расширенному имени с помощью деклараций пространства имен в области действия которых находится данный элемент xsl:attribute, но без обращения к какой-либо декларации пространства имен по умолчанию.

Если имеется атрибут namespace, он тоже интерпретируется как шаблон значения атрибута. Строка, которая получается после его обработки, должна быть ссылкой URI. Однако если эта строка не является синтаксически корректной ссылкой URI, ошибка фиксироваться не будет. Если строка пуста, расширенное имя этого атрибута имеет пустой URI пространства имен. В противном случае, эта строка используется как URI пространства имен для расширенного имени создаваемого атрибута. Локальная часть QName, задаваемая атрибутом name, используется как локальная часть расширенного имени создаваемого атрибута.

При выборе префикса для вывода созданного атрибута в виде XML XSLT процессоры могут воспользоваться префиксом QName, указанным в атрибуте name. Однако процессоры не обязаны делать именно так, а если префиксом является xmlns, то им так делать и не разрешается. Таким образом, хотя следующая инструкция ошибки не вызовет

<xsl:attribute name="xmlns:xsl" 
namespace="whatever">http://www.w3.org/1999/XSL/Transform</xsl:attribute>

она не приведет к появлению декларации пространства имен.

Добавленный к элементу атрибут заменяет любой из уже имевшихся атрибутов этого элемента с таким же расширенным именем.

Возможные ошибки:

Замечание: Если xsl:attribute содержит текстовый узел с символом перехода на новую строку (newline), то выводимый XML должен содержать ссылку на символ. Например,
<xsl:attribute name="a">x

y</xsl:attribute>
будет давать на выходе
a="x&#xA;y"
(или любую эквивалентную этому ссылку на символ). На выходе XML не может появиться
a="x
y"
Это сделано потому, что XML 1.0 требует, чтобы символы newline в значениях атрибутов были преобразованы в пробелы (нормализованы), тогда как ссылки на символ newline нормализации не подлежат. Значения атрибута в рассматриваемой модели данных представляют собой значение атрибута после нормализации. Если символ newline, появившийся в значении атрибута в дереве, был представлен символом newline, а не ссылкой на символ, то в дереве после повторной обработки XML значение этого атрибута будет содержать уже не newline, а пробел, т.е. такое дерево будет показано неправильно.

7.1.4 Именованные наборы атрибутов

<!-- Category: top-level-element -->
<xsl:attribute-set
  name = qname
  use-attribute-sets = qnames>
  <!-- Content: xsl:attribute* -->
</xsl:attribute-set>

Элемент xsl:attribute-set определяет именованный набор атрибутов. Название для этого набора атрибутов определяется атрибутом name. Значением атрибута name является QName, которое приводится к расширенному имени как описано в главе [2.4 Полные имена]. Содержимое элемента xsl:attribute-set состоит из нуля или нескольких элементов xsl:attribute, которые определяют атрибуты в этом наборе.

Чтобы использовать набор атрибутов в элементах xsl:element, xsl:copy (см. [7.5 Копирование]) или xsl:attribute-set, задается атрибут use-attribute-sets. Значением атрибута use-attribute-sets является перечень названий наборов атрибутов через пробел. Каждое название указывается как QName, которое приводится к расширенному имени как было описано в [2.4 Полные имена]. Указание атрибута use-attribute-sets равнозначно добавлению элементов xsl:attribute для каждого атрибута в каждом именованном наборе атрибутов в начало содержимого того элемента, где этот атрибут use-attribute-sets находится, причем в том же порядке как названия этих наборов были перечислены в атрибуте use-attribute-sets. Если в результате использования атрибутов use-attribute-sets в элементах xsl:attribute-set набор атрибутов начинает прямо или косвенно использовать сам себя, фиксируется ошибка.

Наборы атрибутов можно также использовать, указывая в фиксированном конечном элементе атрибут xsl:use-attribute-sets. Значением атрибута xsl:use-attribute-sets является перечень названий наборов атрибутов через пробел. Использование атрибута xsl:use-attribute-sets дает тот же результат, как использование атрибута use-attribute-sets в xsl:element с тем дополнительным ограничением, что атрибуты, указанные в фиксированном конечном элементе, сами обрабатываются так, как если бы они были заданы элементами xsl:attribute прежде всех настоящих элементов xsl:attribute, но после всех элементов xsl:attribute, подставляемых атрибутом xsl:use-attribute-sets. Таким образом, для фиксированного конечного элемента первыми будут добавлены атрибуты из наборов, названных в атрибуте xsl:use-attribute-sets, и именно в том порядке, как они были перечислены в этом атрибуте. Затем будут добавлены атрибуты, указанные в фиксированном конечном элементе. И наконец, будут добавлены все атрибуты, заданные элементами xsl:attribute. Поскольку добавление атрибута к элементу замещает любой из уже имевшихся в этом элементе атрибутов c тем же самым названием, это означает, что атрибуты, заданные в наборах атрибутов, могут быть переопределены атрибутами, указанными в самом фиксированном конечном элементе.

Шаблон в каждом элементе xsl:attribute из элемента xsl:attribute-set обрабатывается при каждом использовании данного набора атрибутов. При обработке используются те же самые текущий узел и текущий набор узлов, что и для обработки элемента, содержащего атрибут use-attribute-sets или xsl:use-attribute-sets. Однако у элемента xsl:attribute иное местоположение в стиле, чем у элемента, имеющего атрибут use-attribute-sets или xsl:use-attribute-sets, а это определяет, какие привязки переменных контекста будут видимы (см. [11 Переменные и параметры]). Таким образом, видимы будут лишь переменные и параметры, декларированные элементами верхнего уровня xsl:variable и xsl:param.

В следующем примере сперва создается именованный набор атрибутов title-style, а затем используется в правиле шаблона.

<xsl:template match="chapter/heading">
  <fo:block quadding="start" xsl:use-attribute-sets="title-style"> 
    <xsl:apply-templates/>
  </fo:block>
</xsl:template> 

<xsl:attribute-set name="title-style">
  <xsl:attribute name="font-size">12pt</xsl:attribute>
  <xsl:attribute name="font-weight">bold</xsl:attribute>
</xsl:attribute-set>

Несколько деклараций наборов атрибутов, имеющих одно и то же расширенное имя, объединяются вместе. Атрибут из определения, которое имеет более высокий приоритет импорта, обладает приоритетом над атрибутом из определения с более низким приоритетом импорта. Когда два набора атрибутов, имеющих одно и то же расширенное имя и одинаковый приоритет импорта, содержат один и тот же атрибут, фиксируется ошибка, если не будет декларации набора атрибутов с еще более высоким приоритетом импорта, так же содержащим этот атрибут. XSLT процессор может сигнализировать о такой ошибке. Если он этого не делает, то должен обработать ошибку сам, выбирая среди деклараций, определяющих этот атрибут и имеющих наивысший приоритет импорта, ту, которая в стиле была дана последней. Местонахождение в наборе атрибутов имеет значение при объединении атрибутов в данный набор. Когда же набор атрибутов используется, никакой разницы нет.

7.2 Создание текста

Шаблон также может содержать текстовые узлы. Каждый текстовый узел в шаблоне, оставшийся после удаления пробельных символов, описанного в главе [3.4 Удаление пробельных символов], создаст в конечном дереве текстовый узел с тем же самым строковым значением. Смежные текстовые узлы в конечном дереве автоматически объединяются.

Заметим, что текст обрабатывается на уровне дерева. Таким образом, разметка &lt; в шаблоне будет представлена в дереве стиля текстовым узлом, содержащим символ <. В результате в конечном дереве будет создан текстовый узел, содержащий символ <. Если конечное дерево представляется в виде XML документа, последний будет представлен разметкой &lt; или эквивалентной ссылкой на символ (при условии, что маскирование вывода не было блокировано, как описано в [16.4 Запрет маскирования при выводе]).

<!-- Category: instruction -->
<xsl:text
  disable-output-escaping = "yes" | "no">
  <!-- Content: #PCDATA -->
</xsl:text>

Символы фиксированных данных также могут быть помещены в элемент xsl:text. Такое окружение может отменить режим удаления пробельных символов (см. [3.4 Удаление пробельных символов]), но не влияет на то, как эти символы впоследствии будут обрабатываться XSLT процессором.

Замечание: Атрибуты xml:lang и xml:space не обрабатываются в XSLT как-либо особо. Например,

7.3 Создание инструкций обработки

<!-- Category: instruction -->
<xsl:processing-instruction
  name = { ncname }>
  <!-- Content: template -->
</xsl:processing-instruction>

Для создания узла инструкции обработки используется элемент xsl:processing-instruction. Содержимое элемента xsl:processing-instruction является шаблоном для строкового значения узла инструкции обработки. Элемент xsl:processing-instruction имеет обязательный атрибут name, который определяет название данного узла инструкции обработки. Значение атрибута name интерпретируется как шаблон значения атрибута.

Например,

<xsl:processing-instruction name="xml-stylesheet">href="book.css"
 type="text/css"</xsl:processing-instruction>

создаст инструкцию обработки

<?xml-stylesheet href="book.css" type="text/css"?>

Если строка, полученная после обработки атрибута name, не является ни NCName, ни PITarget, фиксируется ошибка. XSLT процессор может сигнализировать о такой ошибке. Если он этого не делает, то должен обработать ее сам, отказавшись поместить в конечное дерево соответствующую инструкцию обработки.

Замечание: Это означает что xsl:processing-instruction нельзя использовать для вывода XML декларации. Вместо нее должен использоваться элемент xsl:output (см. [16 Вывод]).

Если при обработке содержимого xsl:processing-instruction создаются узлы, не являющиеся текстовыми, фиксируется ошибка. XSLT процессор может сигнализировать о такой ошибке. Если он этого не делает, то должен обработать ее сам, игнорируя неправильные узлы вместе с их содержимым.

Если результат обработки xsl:processing-instruction содержит строку ?>, фиксируется ошибка. XSLT процессор может сигнализировать об этой ошибке. Если он этого не делает, то должен обработать ее сам, поставив пробел после всех символов of ?, за которыми следовал символ >.

7.4 Создание комментариев

<!-- Category: instruction -->
<xsl:comment>
  <!-- Content: template -->
</xsl:comment>

Для создания в конечном дереве узла комментариев используется элемент xsl:comment. Содержимое элемента xsl:comment является шаблоном для строкового значения данного узла комментария.

Например,

<xsl:comment>This file is automatically generated. Do not edit!</xsl:comment>

создаст следующий комментарий

<!--This file is automatically generated. Do not edit!-->

Если при обработке содержимого xsl:comment создаются узлы, не являющиеся строковыми, фиксируется ошибка. XSLT процессор может сигнализировать о такой ошибке. Если он этого не делает, то должен обработать ее сам, игнорируя неправильные узлы вместе с их содержимым.

Если результат обработки содержимого xsl:comment содержит строку -- или заканчивается символом -, фиксируется ошибка. XSLT процессор может сигнализировать о такой ошибке. Если он этого не делает, он должен сам обработать ошибку, поставив пробел после всех символов -, за которыми следует либо другой символ -, либо конец строки.

7.5 Копирование

<!-- Category: instruction -->
<xsl:copy
  use-attribute-sets = qnames>
  <!-- Content: template -->
</xsl:copy>

Элемент xsl:copy дает простой способ копировать текущий узел. В результате обработки элемента xsl:copy создается копия текущего узла. Узлы пространства имен текущего узла копируются автоматически как есть, однако ни атрибуты, ни потомки этого узла автоматически не копируются. Содержимое элемента xsl:copy является шаблоном для атрибутов и непосредственных потомков создаваемого узла. Указанное содержимое элемента обрабатывается для узлов только тех типов, которые могут иметь атрибуты или потомки (т.е. для корневых узлов и узлов элементов).

Элемент xsl:copy может иметь атрибут use-attribute-sets (см. [7.1.4 Именованные наборы атрибутов]). Последний используется только при копировании узлов элементов.

Корневой узел обрабатывается особым образом, поскольку корневой узел в конечном дереве создается неявно. Если текущий узел является корневым, то xsl:copy не будет создавать корневого узла, а будет использован только шаблон его содержимого.

Например, тождественное преобразование может быть записано с помощью xsl:copy следующим образом:

<xsl:template match="@*|node()">
  <xsl:copy>
    <xsl:apply-templates select="@*|node()"/>
  </xsl:copy>
</xsl:template>

Когда текущий узел является атрибутом, если попытка использовать xsl:attribute для создания нового атрибута с тем же именем что и текущий узел приводит к ошибке, то ошибкой будет также использовать xsl:copy (см. [7.1.3 Создание атрибутов с помощью xsl:attribute]).

Следующий пример показывает как атрибуты xml:lang могут быть легко скопированы из исходного дерева в конечное. Если в стиле определен следующий именованный шаблон:

<xsl:template name="apply-templates-copy-lang"> 
 <xsl:for-each select="@xml:lang">
   <xsl:copy/>
 </xsl:for-each> 
 <xsl:apply-templates/>
</xsl:template>

то вместо

<xsl:apply-templates/>

можно легко сделать

<xsl:call-template name="apply-templates-copy-lang"/>

если необходимо скопировать атрибут xml:lang.

7.6 Вычисление подставляемого текста

В шаблоне для вычисления генерируемого текста, например, при выделении текста из исходного дерева или подстановке значения переменной может использоваться элемент xsl:value-of. Делается это в элементе xsl:value-of с помощью выражения, представленного как значение атрибута select. Заключив в фигурные скобки ({}), выражения можно также использовать в значении атрибутов фиксированных конечных элементов.

7.6.1 Создание текста с помощью xsl:value-of

<!-- Category: instruction -->
<xsl:value-of
  select = string-expression
  disable-output-escaping = "yes" | "no" />

Для создания текстового узла в конечном дереве используется элемент xsl:value-of. Обязательный атрибут select является выражением. Это выражение обрабатывается, а полученный объект преобразуется в строку как при вызове функции string. Эта строка задает строковое значение создаваемого текстового узла. Если строка пустая, текстовый узел создаваться не будет. Созданный текстовый узел будет объединен с любыми соседствующими с ним текстовыми узлами.

Чтобы скопировать набор узлов в конечное дерево, не преобразуя его в строку, можно использовать элемент xsl:copy-of. См. [11.3 Использование значений переменных и параметров с конструкцией xsl:copy-of].

Например, в следующем примере из элемента person с атрибутами given-name и family-name создается параграф HTML. Этот параграф будет содержать значение атрибута given-name из текущего узла, за которым следуют пробел и значение атрибута family-name того же текущего узла.

<xsl:template match="person">
  <p>
   <xsl:value-of select="@given-name"/>
   <xsl:text> </xsl:text>
   <xsl:value-of select="@family-name"/>
  </p>
</xsl:template>

В другом примере параграф HTML создается из элемента person, имеющего непосредственными потомками элементы given-name и family-name. Полученный параграф будет содержать строковое значение первого элемента given-name - непосредственного потомка текущего узла, затем последует пробел и строковое значение первого встретившегося элемента family-name, являющегося непосредственным потомком текущего узла.

<xsl:template match="person">
  <p>
   <xsl:value-of select="given-name"/>
   <xsl:text> </xsl:text>
   <xsl:value-of select="family-name"/>
  </p>

</xsl:template>

В следующем примере каждому элементу procedure предшествует параграф, содержащий уровень безопасности для этой процедуры. Предполагается, что уровень безопасности, соответствующий процедуре, определяется атрибутом security в данном элементе процедуры или в элементе, который является предком этой процедуры. Предполагается также, что если несколько таких элементов имеет атрибут security, то уровень безопасности определяется элементом, самым близким к этой процедуре.

<xsl:template match="procedure">
  <fo:block>
    <xsl:value-of select="ancestor-or-self::*[@security][1]/@security"/>
  </fo:block>
  <xsl:apply-templates/>
</xsl:template>

7.6.2 Шаблоны значений атрибутов

В значении атрибута, которое интерпретируется как шаблон значения атрибута, например, в атрибуте в фиксированном конечном элементе, можно использовать выражение, окружив его фигурными скобками ({}). При обработке шаблона значения атрибута данное выражение с окружающими его фигурными скобками заменяется результатом обработки этого выражения, а полученный объект преобразуется в строку как при вызове функции string. В стиле XSLT в значении атрибута фигурные скобки не распознаются, если не было специально указано, что этот атрибут обрабатывается как шаблон значения атрибута. В сводном синтаксисе элемента значение таких атрибутов ставится в фигурные скобки.

Замечание: Не все атрибуты интерпретируются как шаблоны значений атрибутов. Атрибуты, значением которых является выражение или образец, атрибуты элементов верхнего уровня, а также атрибуты, ссылающиеся на именованные объекты XSLT, не интерпретируются. Кроме того, в качестве шаблонов значений атрибутов не интерпретируются атрибуты xmlns, иначе это не согласовалось бы с соответствующими рекомендациями спецификации XML Namespaces.

В следующем примере из исходного элемента photograph создается конечный элемент img, значение атрибута src в элементе img вычисляется по значению переменной image-dir и строковому значению непосредственного потомка href элемента photograph, значение атрибута width в элементе img вычисляется по значению атрибута width непосредственного потомка size элемента photograph:

<xsl:variable name="image-dir">/images</xsl:variable>

<xsl:template match="photograph">
<img src="{$image-dir}/{href}" width="{size/@width}"/>
</xsl:template>

Из исходного кода

<photograph>
  <href>headquarters.jpg</href>
  <size width="300"/>
</photograph>

будет получено

<img src="/images/headquarters.jpg" width="300"/>

При обработке шаблона значения атрибута двойная левая или правая фигурные скобки за пределами выражения будут заменены на одинарную фигурную скобку. Если в шаблоне значения атрибута за пределами выражения обнаружена правая фигурная скобка, но за ней нет второй правой фигурной скобки, фиксируется ошибка. В выражении внутри Literal правая фигурная скобка не воспринимается как завершающая это выражение.

В выражении фигурные скобки рекурсивно не обрабатываются. Например, использовать:

<a href="#{id({@ref})/title}">

не разрешается. Вместо этого воспользуйтесь просто:

<a href="#{id(@ref)/title}">

7.7 Нумерация

<!-- Category: instruction -->
<xsl:number
  level = "single" | "multiple" | "any"
  count = pattern
  from = pattern
  value = number-expression
  format = { string }
  lang = { nmtoken }
  letter-value = { "alphabetic" | "traditional" }
  grouping-separator = { char }
  grouping-size = { number } />

Чтобы поместить в конечное дерево форматированное число, используется элемент xsl:number. Подставляемое число может быть задано выражением. Атрибут value содержит выражение, которое обрабатывается, а полученный объект преобразуется в число, как при вызове функции number. Затем это число округляется до целого и преобразуется в строку с помощью атрибутов, описанных в [7.7.1 Атрибуты преобразования числа в строку]. В данном контексте значение каждого из этих атрибутов интерпретируется как шаблон значения атрибута. После преобразования полученная строка подставляется в конечное дерево. Например, в следующем примере требуется отсортированный набор чисел:

<xsl:template match="items">
  <xsl:for-each select="item">
    <xsl:sort select="."/>
    <p> 
      <xsl:number value="position()" format="1. "/>
      <xsl:value-of select="."/>
    </p>
  </xsl:for-each>
</xsl:template>

Если атрибут value не указан, элемент xsl:number расставляет числа в зависимости от позиции текущего узла в исходном дереве. Следующие атрибуты определяют, как должен нумероваться текущий узел:

Кроме того, атрибуты, описанные в главе [7.7.1 Атрибуты преобразования числа в строку], используются для преобразования числа в строку, как и в случае когда указан атрибут value.

Сперва элемент xsl:number строит список положительных целых чисел, используя атрибуты level, count и from:

Затем полученный перечень чисел преобразуется в строку с помощью атрибутов, описанных в главе [7.7.1 Атрибуты преобразования чисел в строки]. В данном контексте значение каждого из этих атрибутов интерпретируется как шаблон значения атрибута. Строка, полученная после преобразования, подставляется в конечное дерево.

Следующий пример будет нумеровать записи в упорядоченном списке:

<xsl:template match="ol/item">
  <fo:block>
    <xsl:number/><xsl:text>. </xsl:text><xsl:apply-templates/>
  </fo:block>
<xsl:template>

Следующие два правила будут нумеровать элементы title. Правила предназначаются для документа, в котором есть несколько глав, затем следует несколько приложений, причем и главы, и приложения имеют разделы, а те, в свою очередь, содержат подразделы. Главы нумеруются как 1, 2, 3, приложения нумеруются как A, B, C, разделы нумеруются 1.1, 1.2, 1.3, разделы в приложениях нумеруются A.1, A.2, A.3.

<xsl:template match="title">
  <fo:block>
     <xsl:number level="multiple"
                 count="chapter|section|subsection"
                 format="1.1 "/>
     <xsl:apply-templates/>
  </fo:block>
</xsl:template>

<xsl:template match="appendix//title" priority="1">
  <fo:block>
     <xsl:number level="multiple"
                 count="appendix|section|subsection"
                 format="A.1 "/>
     <xsl:apply-templates/>
  </fo:block>
</xsl:template>

Следующий пример последовательно нумерует примечания в главе:

<xsl:template match="note">
   <fo:block>
     <xsl:number level="any" from="chapter" format="(1) "/>
     <xsl:apply-templates/>
  </fo:block> 
</xsl:template>

Следующий пример в HTML документе будет нумеровать элементы H4, используя метки, состоящие из трех частей:

<xsl:template match="H4">
 <fo:block>
   <xsl:number level="any" from="H1" count="H2"/>
   <xsl:text>.</xsl:text> 
   <xsl:number level="any" from="H2" count="H3"/>
   <xsl:text>.</xsl:text>
   <xsl:number level="any" from="H3" count="H4"/>
   <xsl:text> </xsl:text>
   <xsl:apply-templates/>
 </fo:block>
</xsl:template>

7.7.1 Атрибуты преобразования числа в строку

Описанные далее атрибуты используются чтобы контролировать преобразование набора чисел в строку. Числа являются целыми и больше нуля. Все атрибуты являются необязательными.

Главным атрибутом является format. По умолчанию атрибут format имеет значение 1. Атрибут format разбивается на последовательность лексем, каждая из которых представляет собой максимальную последовательность alphanumeric символов или максимальную последовательность символов, не являющихся alphanumeric. Alphanumeric здесь означает любой символ, который имеет категорию Unicode Nd, Nl, No, Lu, Ll, Lt, Lm или Lo. Alphanumeric лексемы (лексемы формата) определяют формат, которым должен использоваться для каждого числа в списке. Если первая лексема является не alphanumeric, создаваемая строка начнется с этой лексемы. Если последняя лексема является не alphanumeric, создаваемая строка закончится этой лексемой. Не-alphanumeric лексемы, оказавшиеся между двумя лексемами форматирования, являются разделителями лексем, которые должны использоваться в списке для объединения чисел. n-ая лексема форматирования будет использоваться в списке для форматирования n-го числа. Если чисел больше чем лексем форматирования, для форматирования оставшихся чисел будет использоваться последняя лексема форматирования. Если лексемы форматирования отсутствуют, для форматирования всех чисел должна использоваться лексема форматирования 1. Эта лексема форматирования указывает строку, которая должна использоваться для представления числа 1. Каждое число, начиная со второго, будет отделено от предыдущего числа либо лексемой разделителя, которая предшествует лексеме форматирования, использованной для форматирования этого числа, либо, если лексемы разделителя отсутствуют, символом точки (.).

Лексемы форматирования включают как подмножество разрешенные значения атрибута type в элементе OL из HTML 4.0 и интерпретируются следующим образом:

Если нумерация выполняется последовательностью букв, атрибут lang указывает, алфавит какого языка следует использовать. Атрибут имеет тот же самый диапазон значений, что и xml:lang в [XML]. Если значение lang не было указано, язык следует определить из системного окружения. Разработчикам процессоров следует документировать, для каких языков поддерживается нумерация.

Замечание: Разработчики не должны выдвигать каких-либо предположений о порядке нумерации в тех или иных языках, и должны должным образом исследовать те языки, которые они берутся поддерживать. Порядок нумерации во многих языках сильно отличается от принятого в английском языке.

Атрибут letter-value устраняет неясности в последовательностях нумерации, использующих буквы. Во многих языках обычно используются две основные последовательности нумерации, использующие буквы. В одной из них нумерация производится буквенными значениями в алфавитном порядке, в другой же числовое значение каждому пункту назначается по-другому, так как это принято для данного языка. В английском языке это будет соответствовать последовательностям нумерации, задаваемым лексемами форматирования a и i. В некоторых языках первый член обеих последовательностей одинаков, а потому одной лексемы форматирования будет недостаточно. Значение alphabetic указывает алфавитную последовательность, значение traditional - альтернативную. Если атрибут letter-value не указан, порядок разрешения любых неоднозначностей определяется реализацией.

Замечание: Два процессора, отвечающие спецификации XSLT, могут преобразовывать число в разные строки. Некоторые XSLT процессоры не имеют поддержки некоторых языков. Более того, для любого конкретного языка могут отличаться способы преобразования, не специфицируемые атрибутами xsl:number. В будущих версиях XSLT могут появиться дополнительные атрибуты, дающие контроль над такими вариациями. Для этой же цели реализации могут также использовать в xsl:number атрибуты из пространства имен, привязанного к реализации.

Атрибут grouping-separator определяет разделитель для группировки в десятичной нумерации (например, тысяч). Необязательный атрибут grouping-size указывает размер для группировки (обычно, 3). Например, grouping-separator="," и grouping-size="3" должны определить числа в формате 1,000,000. Если указан только один из атрибутов grouping-separator или grouping-size, он игнорируется.

Некоторые примеры спецификаций преобразования:

Назад | Содержание | Вперед