РОЛ / Справочная информация

Язык преобразований XSL (XSLT)
Версия 1.0

Рекомендация W3C от 16 ноября 1999

Данный документ представляет собой перевод спецификации XSL Transformations (XSLT) Version 1.0 (W3C Recommendation) на русский язык. При этом нормативным документом считается оригинальная спецификация на английском языке, которую можно найти по адресу http://www.w3.org/TR/1999/REC-xslt-19991116. Перевод спецификации на русский язык представлен на страницах портала "Россия-Он-Лайн": http://www.rol.ru/news/it/helpdesk/xslt01.htm Перевод выполнен Радиком Усмановым, Luxoft (IBS)
Представленный документ может содержать ошибки перевода.
Данная версия:
http://www.w3.org/TR/1999/REC-xslt-19991116
(доступна в форматах XML и HTML)
Последняя версия:
http://www.w3.org/TR/xslt
Предыдущие версии:
http://www.w3.org/TR/1999/PR-xslt-19991008
http://www.w3.org/1999/08/WD-xslt-19990813
http://www.w3.org/1999/07/WD-xslt-19990709
http://www.w3.org/TR/1999/WD-xslt-19990421
http://www.w3.org/TR/1998/WD-xsl-19981216
http://www.w3.org/TR/1998/WD-xsl-19980818
Редактор:
James Clark mailto:jjc@jclark.com

Copyright © 1999 W3C ® (MIT, INRIA, Keio), Все права защищены. Обязательства W3C, правила, касающиеся торговой марки, применения документа и лицензирования программного обеспечения.

Предисловие

Данная спецификация определяет синтаксис и семантику XSLT, языка преобразований XML документов в другие XML документы.

XSLT создавался для применения в XSL, языке стилей для XML. Помимо XSLT, XSL содержит словарь XML для описания форматирования. XSL определяет стиль XML документа, используя XSLT чтобы описать, каким именно образом представленный документ преобразуется в другой XML документ, использующий данный словарь форматирования.

Кроме того, XSLT построен так, чтобы использоваться независимо от XSL. Вместе с тем XSLT не позиционируется как полноценный универсальный язык преобразований XML. Скорее наоборот, прежде всего он предназначен для тех видов преобразований, которые необходимы когда XSLT используется как часть XSL.

Статус документа

Данный документ был рассмотрен членами W3C, другими заинтересованными сторонами и одобрен Директором в качестве Рекомендации W3C. Это окончательный документ, который можно использовать как материал для ссылки или цитирования в других документах в качестве нормативного материала. Участие W3C в разработке данной Рекомендации заключается в привлечении внимания к представленной спецификации и способствовании ее всеобщему распространению. Тем самым повышается функциональность и универсальность Сети.

Перечень ошибок, выявленных в этой спецификации, доступен по адресу http://www.w3.org/1999/11/REC-xslt-19991116-errata.

Комментарии к данной спецификации можно выслать по адресу xsl-editors@w3.org, доступен также архив комментариев. Открытое обсуждение XSL, включая XSL Transformations, происходит в почтовом списке рассылки XSL-List.

Нормативной силой наделен лишь английский вариант этой спецификации. Однако по адресу http://www.w3.org/Style/XSL/translations.html можно найти перевод этого документа на другие языки.

Перечень текущих Рекомендаций W3C, а также другие технические документы можно найти по адресу http://www.w3.org/TR.

Данная спецификация была разработана в рамках проекта W3C Style.

Содержание

1 Введение
2 Структура стиля
2.1 Пространство имен XSLT
2.2 Элемент стиля
2.3 Фиксированный конечный элемент как стиль
2.4 Полные имена
2.5 Обработка, совместимая с последующими версиями
2.6 Комбинированные стили
2.6.1 Включение стилей
2.6.2 Stylesheet Import
2.7 Встроенные стили
3 Модель данных
3.1 Непосредственный потомок корневого узла
3.2 Базовый URI
3.3 Неразобранные сущности
3.4 Удаление пробельных символов
4 Выражения
5 Правила шаблона
5.1 Схема обработки
5.2 Образцы
5.3 Определение правил шаблона
5.4 Использование правил шаблона
5.5 Разрешение конфликтов в правилах шаблона
5.6 Переопределение правил шаблона
5.7 Режимы
5.8 Встроенные правила шаблона
6 Именованные шаблоны
7 Создание конечного дерева
7.1 Создание элементов и атрибутов
7.1.1 Фиксированные конечные элементы
7.1.2 Создание элементов с помощью xsl:element
7.1.3 Создание атрибутов с помощью xsl:attribute
7.1.4 Именованные наборы атрибутов
7.2 Создание текста
7.3 Создание инструкций обработки
7.4 Создание комментариев
7.5 Копирование
7.6 Вычисление подставляемого текста
7.6.1 Создание текста с помощью xsl:value-of
7.6.2 Шаблоны значений атрибутов
7.7 Нумерация
7.7.1 Атрибуты преобразования числа в строку
8 Повторение
9 Обработка с условием
9.1 Обработка с условием xsl:if
9.2 Обработка с условием xsl:choose
10 Сортировка
11 Переменные и параметры
11.1 Фрагменты конечного дерева
11.2 Значения переменных и параметров
11.3 Использование значений переменных и параметров с конструкцией xsl:copy-of
11.4 Переменные и параметры верхнего уровня
11.5 Переменные и параметры в шаблонах
11.6 Передача параметров шаблону
12 Дополнительные функции
12.1 Множественные исходные документы
12.2 Ключи
12.3 Форматирование чисел
12.4 Различные дополнительные функции
13 Сообщения
14 Расширения
14.1 Элементы расширения
14.2 Функции расширения
15 Откат
16 Вывод
16.1 Метод вывода XML
16.2 Метод вывода HTML
16.3 Метод вывода Text
16.4 Запрет маскирования при выводе
17 Соответствие спецификации
18 Нотация

Приложения

A Ссылки
A.1 Нормативные ссылки
A.2 Остальные ссылки
B Справочник синтаксиса элементов
C Фрагмент DTD для стилей XSLT (пояснения к спецификации)
D Примеры (пояснения к спецификации)
D.1 Пример документа
D.2 Пример данных
E Благодарности (пояснения к спецификации)
F Изменения по внесенным рекомендациям (пояснения к спецификации)
G Характеристики для рассмотрения в будущих версиях XSLT (пояснения к спецификации)
H Словарь (пояснения к спецификации)

1 Введение

В данной спецификации определяется синтаксис и семантика языка XSLT. Преобразование в языке XSLT предстает в виде корректного (well-formed) XML документа [XML], соответствующего требованиям для пространств имен из Рекомендации XML [XML Names]. Оно может содержать как элементы, определяемые в XSLT, так и элементы, которые в XSLT не определены. Элементы, определяемые в XSLT, отличаются принадлежностью определенному пространству имен XML (см. главу [2.1 Пространство имен XSLT]), которое в данной спецификации мы называем пространством имен XSLT. Таким образом, данная спецификация - это определение синтаксиса и семантики пространства имен XSLT.

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

Преобразование, выраженное через XSLT, называется стилем (stylesheet). Так сделано потому, что в случае, когда XSLT приводится к словарю форматирования XSL, данное преобразование выполняет функции стиля.

Данный документ не конкретизирует, каким образом стиль XSLT привязывается к документу XML. Рекомендуется чтобы процессоры XSL поддерживали механизм, описанный в документе [Стиль XML]. Когда этот или какой-либо другой механизм дает последовательность из нескольких стилей XSLT, которые должны быть применены к XML-документу одновременно, это будет то же самое, как если бы использовался один стиль, поочередно импортирующий все члены этой последовательности стилей (см. [2.6.2 Импорт стилей]).

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

Чтобы получить фрагмент в конечном дереве, шаблон обрабатывается для определенного элемента в исходном документе. Шаблон может содержать элементы, определяющие фиксированную структуру конечного элемента. Шаблон может также содержать элементы из пространства имен XSLT, дающие инструкции по созданию фрагментов конечного дерева. При обработке шаблона каждая инструкция обрабатывается и заменяется на полученный фрагмент конечного дерева. Инструкции могут находить в исходном дереве и обрабатывать элементы-потомки. При обработке элемента-потомка в конечном дереве создается фрагмент путем нахождения соответствующего правила шаблона и обработки его шаблона. Заметим, что элементы обрабатываются только если они были выбраны в ходе выполнения инструкции. Конечное дерево строится после нахождения правила шаблона для корневого узла и обработки в нем шаблона.

В ходе поиска соответствующего правила шаблона может выясниться, что данному элементу соответствует не одно, а сразу несколько правил. Однако использоваться будет только одно правило шаблона. Методика для определения, какое из правил шаблона должно использоваться, описывается в разделе [5.5 Разрешение конфликтов в правилах шаблона].

Шаблон даже сам по себе наделен значительной мощностью: он может создавать структуры произвольной сложности, извлекать строковые значения из любых мест исходного дерева, создавать структуры, повторяющие появление элементов в исходном дереве. Для простых преобразований, когда структура конечного дерева не связана со структурой исходного дерева, стиль часто образуется одним шаблоном, который используется как шаблон для всего конечного дерева. К этому типу часто относится преобразование XML документов, которые содержат некие данные (см. [D.2 Пример данных]). Для таких стилей в XSLT предусмотрен упрощенный синтаксис (см. [2.3 Фиксированный конечный элемент как стиль]).

Если обрабатывается шаблон, то это всегда делается отталкиваясь от текущего узла и текущего набора узлов. Текущий узел всегда является членом текущего набора узлов. В XSLT многие операции привязаны к текущему узлу. И лишь несколько инструкций меняют текущий набор узлов или текущий узел (см. [5 Правила шаблона] и [8 Повторение]). При обработке любой из этих инструкций текущий набор узлов заменяется новым набором узлов, а каждый член этого нового набора по очереди становится текущим узлом. После того как обработка инструкции завершена, текущий узел и текущий набор узлов становится такими, каким они были до обработки этой инструкции.

Для выбора элементов для обработки, обработки при условии и генерации текста XSLT использует язык выражений, сформулированный в [XPath].

XSLT оставляет две "зацепки" для дальнейших расширений языка. Первая связана с расширением набора элементов инструкций, используемых в шаблонах, а вторая - с расширением набора функций, используемых в выражениях XPath. Обе эти зацепки основаны на использовании пространства имен XML. Механизм их реализации в данной версии XSLT не конкретизируется. См. главу [14 Расширения].

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

Для описания синтаксиса элементов, определенных в XSLT, используется общая нотация синтаксиса элементов, описаная в главе [18 Нотация].

Для стилей XSLT должен использоваться тип среды MIME text/xml или application/xml [RFC2376]. Возможно, специально для работы со стилями XSLT будет зарегистрирован еще один тип среды. Если это произойдет, то он тоже может быть использован.

2 Структура стиля

2.1 Пространство имен XSLT

Пространство имен XSLT имеет URI http://www.w3.org/1999/XSL/Transform.

Замечание: Число 1999 в этом URI показывает год, в который этот URI был принят W3C. И это не версия используемого XSLT, которая задается атрибутами (см. главы [2.2 Элемент стиля] и [2.3 Фиксированный конечный элемент как стиль]).

Чтобы идентифицировать элементы и атрибуты из указанного пространства, XSLT процессоры должны использовать механизм пространства имен XML [Имена XML]. Элементы из пространства имен XSLT распознаются только в стиле, а не в исходном документе. Полный перечень элементов, определенных в XSLT, представлен в Приложении [B Справочник синтаксиса элементов]. Разработчики не должны пополнять пространство имен XSLT дополнительными элементами и атрибутами. Вместо этого любое расширение должно быть вынесено в отдельное пространство имен. Какое бы пространство имен не использовалось для дополнительных элементов инструкций, оно должно быть идентифицировано с помощью механизма элементов расширения, описанного в главе [14.1 Элементы расширения].

Для обращения к элементам из пространства имен XSLT в данной спецификации использует префикс xsl:. Однако в XSLT стиле можно свободно использовать любой префикс при условии, что имеется декларация пространства имен, привязывающая этот префикс к тому же URI пространства имен XSLT.

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

Если элемент из пространства имен XSLT имеет атрибут, чье расширенное имя имеет нулевой URI пространства имен (т.е. атрибут с названием без префиксов), и который не входит в число атрибутов, определенных для этого элемента в данном документе, фиксируется ошибка.

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

2.2 Элемент стиля

<xsl:stylesheet
  id = id
  extension-element-prefixes = tokens
  exclude-result-prefixes = tokens
  version = number>
  <!-- Content: (xsl:import*, top-level-elements) -->
</xsl:stylesheet>

<xsl:transform
  id = id
  extension-element-prefixes = tokens
  exclude-result-prefixes = tokens
  version = number>
  <!-- Content: (xsl:import*, top-level-elements) -->
</xsl:transform>

В XML документе стиль представлен элементом xsl:stylesheet. В качестве синонима xsl:stylesheet можно использовать xsl:transform.

Элемент xsl:stylesheet обязан иметь атрибут version, указывающий какая версия XSLT необходима для этого стиля. Для обсуждаемой версии XSLT значение атрибута должно быть 1.0. Если значение отлично от 1.0, можно использовать режим совместимости с последующими версиями (см. главу [2.5 Обработка, совместимая с последующими версиями]).

Элемент xsl:stylesheet может содержать следующие типы элементов:

  • xsl:import

  • xsl:include

  • xsl:strip-space

  • xsl:preserve-space

  • xsl:output

  • xsl:key

  • xsl:decimal-format

  • xsl:namespace-alias

  • xsl:attribute-set

  • xsl:variable

  • xsl:param

  • xsl:template

Элемент, оказавшийся непосредственным потомком элемента xsl:stylesheet, называется элементом верхнего уровня.

Следующий пример показывает структуру стиля. Многоточием (...) обозначены те места, где опущено значение атрибута или содержимое. Хотя в этом примере показано по одному элементу для каждого разрешенного типа, стиль может не содержать какой-либо из этих элементов, либо содержать сразу несколько его экземпляров.

<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:import href="..."/>

  <xsl:include href="..."/>

  <xsl:strip-space elements="..."/>

  <xsl:preserve-space elements="..."/>

  <xsl:output method="..."/>

  <xsl:key name="..." match="..." use="..."/>

  <xsl:decimal-format name="..."/>

  <xsl:namespace-alias stylesheet-prefix="..." result-prefix="..."/>

  <xsl:attribute-set name="...">
    ...
  </xsl:attribute-set>

  <xsl:variable name="...">...</xsl:variable>

  <xsl:param name="...">...</xsl:param>

  <xsl:template match="...">
    ...
  </xsl:template>

  <xsl:template name="...">
    ...
  </xsl:template>

</xsl:stylesheet>

Порядок появления непосредственных потомков элемента xsl:stylesheet значения не имеет, за исключением элементов xsl:import и обработки ошибки. Пользователи могут располагать элементы по своему усмотрению, а инструментам разработи стилей нет нужды контролировать порядок размещения указанных элементов.

Кроме этого, элемент xsl:stylesheet может содержать любой элемент не из пространства имен XSLT, при условии что расширенное имя этого элемента содержит ненулевой URI пространства имен. Появление таких элементов верхнего уровня не должно сказываться на поведении элементов и функций XSLT, определенных в данном документе. Например, такой элемент верхнего уровня не может заставить xsl:apply-templates использовать другие правила для разрешения конфликтов. Таким образом, XSLT процессор всегда может свободно игнорировать такие элементы верхнего уровня. Более того, процессор обязан игнорировать элемент верхнего уровня, не инициируя ошибки, если не может распознать в нем URI пространства имен. К примеру, такие элементы могут содержать

  • информацию, используемую элементами или функциями расширения (см. [14 Расширения]),

  • информацию о том что следует делать с конечным деревом,

  • информацию о том как получить исходное дерево,

  • метаданные о представленном стиле,

  • структурированную документацию для этого стиля.

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

Для стилей, состоящих из единственного шаблона, для корневого узла можно использовать упрощенный синтаксис. Данный стиль может содержать только один фиксированный конечный элемент (literal result element, см. главу [7.1.1 Фиксированные конечные элементы]). Такой стиль равнозначен стилю с элементом xsl:stylesheet, содержащим правило шаблона с фиксированным конечным элементом, которое для сравнения использует образец /. Например:

<html xsl:version="1.0"
       xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
      xmlns="http://www.w3.org/TR/xhtml1/strict">
  <head>
    <title>Expense Report Summary</title>
  </head>
  <body>
    <p>Total Amount: <xsl:value-of select="expense-report/total"/></p>
  </body>
</html>

что равнозначно

<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns="http://www.w3.org/TR/xhtml1/strict">
<xsl:template match="/">
<html>
  <head>
    <title>Expense Report Summary</title>
  </head>
  <body>
    <p>Total Amount: <xsl:value-of select="expense-report/total"/></p>
  </body>
</html>
</xsl:template>
</xsl:stylesheet>

Фиксированный конечный элемент, являющийся для стиля элементом документа, должен иметь атрибут xsl:version, указывающий версию XSLT, необходимую для этого стиля. Для данной версии XSLT значением этого атрибута должно быть 1.0, значение должно иметь тип Number. Другие фиксированные конечные элементы также должны иметь атрибут xsl:version. Если атрибут xsl:version не равен 1.0, должен быть разрешен режим обработки, совместимый с последующими версиями. (см. главу [2.5 Обработка, совместимая с последующими версиями]).

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

В некоторых ситуациях, единственная возможность для системы узнать, что некий XML документ XSLT процессор должен обрабатывать именно как стиль XSLT - это исследовать сам представленный XML документ самостоятельно. Использование упрощенного синтаксиса усложняет эту задачу.

Замечание: Например, другой язык XML (AXL) также может использовать в элементе документа атрибут axl:version чтобы показать, что XML документ является AXL документом, который необходимо обрабатывать AXL процессором. Если документ имеет оба указанных атрибута axl:version, становится непонятным, следует ли данный документ обрабатывать XSLT процессором или же AXL процессором.

По этой причине упрощенный синтаксис не должен использоваться для XSLT стилей, которые могут оказаться в такой ситуации. Например, такая ситуация может возникать когда стиль XSLT передается как сообщение с типом среды MIME text/xml или application/xml, а получатель использует этот тип среды MIME чтобы определить, как следует обрабатывать это сообщение.

2.4 Полные имена

Название внутреннего объекта XSLT, а именно: именованного шаблона (см. [6 Именованные шаблоны]), режима (см. [5.7 Режимы]), набора атрибутов (см. [7.1.4 Именованные наборы атрибутов]), ключа (см. [12.2 Ключи]), десятичного формата (см. [12.3 Форматирование чисел]), переменной или параметра (см. [11 Переменные и параметры]), задается как QName. Если название имеет префикс, то этот префикс преобразуется в ссылку URI с помощью деклараций пространства имен, в области действия оказался атрибут с этим названием. В качестве названия указанного объекта используется расширенное имя, состоящее из локальной части и, возможно нулевой, ссылки URI. Для названий без префиксов пространство имен по умолчанию не используется.

2.5 Обработка, совместимая с последующими версиями

Режим совместимости с последующими версиями можно использовать для самого элемента, его атрибутов, его потомков и их атрибутов, если имеется элемент xsl:stylesheet с атрибутом version, значение которого отлично от 1.0, или имеется фиксированный конечный элемент, имеющий атрибут xsl:version со значением, отличным от 1.0, либо имеется фиксированный конечный элемент, не имеющий атрибута xsl:version, но элемент документа в стиле использует упрощенный синтаксис (см. [2.3 Фиксированный конечный элемент как стиль]). Фиксированный конечный элемент, имеющий атрибут xsl:version, значение которого равно 1.0, отменяет режим совместимости с последующими версиями для себя, своих атрибутов, своих потомков и их атрибутов.

Если элемент обрабатывается в режиме совместимости с последующими версиями, то:

  • если есть некий элемент верхнего уровня, а XSLT 1.0 такие элементы не позволяет использовать в качестве элементов верхнего уровня, то такой элемент и его содержимое должны быть проигнорированы;

  • если в шаблоне есть некий элемент, а XSLT 1.0 не позволяет в шаблонах использовать такие элементы, то когда этот элемент не обрабатывается, сообщения об ошибке возникать не должно, если же этот элемент уже был обработан, то XSLT должен выполнить откат для этого элемента как описано в главе [15 Откат];

  • если элемент имеет атрибут, который XSLT 1.0 ему иметь не позволяет, или если элемент имеет необязательный атрибут со значением, которое XSLT 1.0 также не позволяет ему иметь, такой атрибут должен быть проигнорирован.

Таким образом, любой процессор XSLT 1.0 должен уметь обработать представленный далее стиль без ошибок, даже несмотря на то, что тот содержит элементы из пространства имен XSLT, которые не были заданы в этой спецификации:

<xsl:stylesheet version="1.1"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:template match="/">
    <xsl:choose>
      <xsl:when test="system-property('xsl:version') >= 1.1">
        <xsl:exciting-new-1.1-feature/>
      </xsl:when>
      <xsl:otherwise>
        <html>
        <head>
          <title>XSLT 1.1 required</title>
        </head>
        <body>
          <p>Sorry, this stylesheet requires XSLT 1.1.</p>
        </body>
        </html>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>
</xsl:stylesheet>
Замечание: Если стиль опосредованно зависит от элемента верхнего уровня, объявленного в XSL более старшей версии чем 1.0, то тогда в этом стиле можно использовать элемент xsl:message с атрибутом terminate="yes" (см. [13 Сообщения]) чтобы гарантировать, что XSLT процессоры, реализующие более ранние версии XSL, не будут втихую игнорировать указанный элемент верхнего уровня. Например,
<xsl:stylesheet version="1.5"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:important-new-1.1-declaration/>

  <xsl:template match="/">
    <xsl:choose>
      <xsl:when test="system-property('xsl:version') &lt; 1.1">
        <xsl:message terminate="yes">
          <xsl:text>Sorry, this stylesheet requires XSLT 1.1.</xsl:text>
        </xsl:message>
      </xsl:when>
      <xsl:otherwise>
        ...
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>
  ...
</xsl:stylesheet>

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

  • если выражение не соответствует синтаксису, заданному грамматикой XPath, то ошибка не должна фиксироваться до тех пор, пока реально не будет затребована обработка этого выражения;

  • если выражение вызывает функцию с названием без префикса, которая не является частью библиотеки XSLT, то ошибка не должна фиксироваться до тех пор, пока данная функция не будет действительно вызвана;

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

2.6 Комбинированные стили

Язык XSLT предоставляет два механизма для комбинирования стилей:

  • механизм включения (include), позволяющий объединять стили без изменения семантики комбинированных стилей, и
  • механизм импорта (import), который позволяет стилям переписывать друг друга.

2.6.1 Включение стилей

<!-- Category: top-level-element -->
<xsl:include
  href = uri-reference />

С помощью элемента xsl:include один стиль XSLT может включить в себя другой стиль XSLT. Элемент xsl:include имеет атрибут href, значением которого является ссылка URI, идентифицирующая включаемый стиль. Относительная ссылка URI обрабатывается относительно базового URI элемента xsl:include (см. [3.2 Базовый URI]).

Элемент xsl:include можно использовать лишь в качестве элемента верхнего уровня.

Включение оперирует деревьями XML. Ресурс, на который указывает атрибут href, обрабатывается как документ XML и обнаруженные в нем непосредственные потомки элемента xsl:stylesheet замещают элемент xsl:include во включающем документе. Тот факт, что те или иные правила шаблона или определения были получены включением, на то как они затем обрабатываются не влияет.

Во включаемом стиле может использоваться упрощенный синтаксис, описанный в главе [2.3 Фиксированный конечный элемент как стиль]. Включаемый стиль обрабатывается точно так же как эквивалентный ему элемент xsl:stylesheet.

Если стиль прямо или опосредовано включает сам себя, фиксируется ошибка.

Замечание: Многократное включение стиля может привести к ошибкам вследствие дублирования деклараций. Такие множественные включения не столь очевидны, если являются косвенными. Например, если стиль B включает стиль A, стиль C включает стиль A, а стиль D включает оба стиля B и C, то A опосредованно включено в D дважды. Если все указанные стили B, C и D являются независимыми, то ошибки можно избежать, если в B выделить все, что не относится к включенному A, в отдельный стиль B' и поменять B так чтобы он просто включал эти B' и A, затем аналогично поступить с C, и, наконец, переписать D так чтобы он включал A, B' и C'.

2.6.2 Импорт стилей

<xsl:import
  href = uri-reference />

С помощью элемента xsl:import один XSLT стиль может импортировать другой стиль XSLT. Импортирование стиля похоже на его включение (см. [2.6.1 Включение стилей]) за исключением того, что определения и правила шаблона в испортирующем стиле имеют приоритет над правилами шаблона и определениями в импортируемом стиле, более детально это будет обсуждаться ниже. Элемент xsl:import имеет атрибут href, значением которого является ссылка URI, идентифицирующая импортируемый стиль. Относительная ссылка URI обрабатывается относительно базового URI элемента xsl:import (см. [3.2 Базовый URI]).

Элемент xsl:import можно использовать только как элемент верхнего уровня. Потомки элемента xsl:import должны предшествовать всем другим элементам, являющимся непосредственными потомкам элемента xsl:stylesheet, в том числе и всем элементам xsl:include. Если для включения стиля используется xsl:include, то все элементы xsl:import из включаемого документа в включающем документе переносятся вверх и ставятся после всех уже имевшихся во включающем документе элементов xsl:import.

Например,

<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:import href="article.xsl"/>
  <xsl:import href="bigfont.xsl"/>
  <xsl:attribute-set name="note-style">
    <xsl:attribute name="font-style">italic</xsl:attribute>
  </xsl:attribute-set>
</xsl:stylesheet>

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

Например, предположим, что

  • стиль A, импортирует стили B и C в указанном порядке:

  • стиль B импортирует стиль D;

  • стиль C импортирует стиль E.

Тогда порядок приоритетов импорта (начиная с наименьшего) будет D, B, E, C и A.

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

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

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

Замечание: Если используется xsl:apply-imports (см. главу [5.6 Переопределение правил шаблона]), то функционирование может быть иным, чем когда этот стиль был импортирован только в этом месте и с наивысшим приоритетом импорта.

2.7 Встроенные стили

Обычно стиль XSLT является полноценным XML документом с элементом xsl:stylesheet в качестве элемента документа. Однако стиль XSLT может вынесен и в другой источник. Возможны два варианта размещения:

  • стиль XSLT может быть помещен как текст в источник, имеющий формат, отличный от XML, либо
  • элемент xsl:stylesheet может появиться в XML документе, но не в качестве элемента документа.

Чтобы содействовать второму варианту размещения, элемент xsl:stylesheet может иметь атрибут ID, который задает уникальный идентификатор.

Замечание: Чтобы такой атрибут можно было использовать с функцией id из XPath, он реально должен быть декларирован в DTD как ID.

Следующий пример показывает, каким образом можно использовать инструкцию обработки xml-stylesheet [Стиль XML] чтобы позволить документу содержать свой собственный стиль. Чтобы найти элемент xsl:stylesheet, ссылка URI использует относительный URI с идентификатором фрагмента:

<?xml-stylesheet type="text/xml" href="#style1"?>
<!DOCTYPE doc SYSTEM "doc.dtd"> <doc>
<head>
<xsl:stylesheet id="style1"
                version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:fo="http://www.w3.org/1999/XSL/Format">
<xsl:import href="doc.xsl"/>
<xsl:template match="id('foo')">
  <fo:block font-weight="bold"><xsl:apply-templates/></fo:block>
</xsl:template>
<xsl:template match="xsl:stylesheet">
  <!-- игнорируется -->
</xsl:template>
</xsl:stylesheet>
</head>
<body>
<para id="foo">
...
</para>
</body>
</doc>
Замечание: Стиль, который вложен в документ, к которому должен быть применен, либо стиль, включенный или импортированный в такой стиль, как правило, должен иметь правило шаблона, сообщающее, что элементы xsl:stylesheet должны быть проигнорированы.

3 Модель данных

Используемая в XSLT модель данных аналогична используемой в XPath с определенными дополнениями, описанными в этом разделе. XSLT оперирует с исходными, конечными документами и документами стилей, используя одну и ту же модель данных. Любые два XML документа, имеющие одно и то же дерево, будут обрабатываться XSLT одинаковым образом.

Инструкции обработки и комментарии в стиле игнорируются: стиль обрабатывается так, как если бы в представляющем его дереве не было представлено ни узлов инструкций обработки, ни узлов комментариев.

3.1 Непосредственный потомок корневого узла

Обычные ограничения для непосредственного потомка корневого узла на конечное дерево не распространяется. Конечное дерево может иметь в качестве непосредственных потомкоы любую последовательность узлов, которые можно использовать как узел элемента. В частности, оно может иметь непосредственным потомком текстовый узел и любое количество узлов элементов. Если вывод осуществляется с помощью метода output из XML (см. главу [16 Вывод]), то может оказаться, что конечное дерево не является корректным XML документом. Однако оно корректной внешней общей разобранной сущностью будет всегда.

Если исходное дерево создано разбором корректного XML документа, корневой узел в исходном дереве автоматически удовлетворяет обычным ограничениям: непосредственным потомком не может быть текстовый узел, а может быть только один элемент. Когда исходное дерево создано как-нибудь иначе, например, с помощью DOM, то обычные ограничения ни на исходное дерево, ни на конечное не действуют.

3.2 Базовый URI

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

3.3 Неразобранные сущности

Корневой узел имеет схему отображения, которая определяет URI для каждой неразобранной сущности, декларированной в DTD данного документа. Этот URI создается из системного идентификатора и публичного идентификатора, указанного в декларации сущности. Чтобы для сущности найти URI, XSLT процессор может воспользоваться публичным идентификатором, вместо того чтобы обращаться к URI, указанному в системном идентификаторе. Если XSLT процессор для построения данного URI не пользуется публичным идентификатором, то он обязан воспользоваться системным идентификатором. Если системный идентификатор является относительным URI, он должен быть преобразован в абсолютный URI, используя в качестве базового URI того ресурса, который содержит декларацию данной сущности [RFC2396].

3.4 Удаление пробельных символов

После построения дерева исходного документа или документа стиля, но перед какой-либо его обработкой XSLT процессором, выполняется очистка (stripping) некоторых текстовых узлов. Текстовый узел вычищается только тогда, когда он содержит одни пробельные символы. При очистке текстовый узел удаляется из дерева документа. На вход процедура очистки получает перечень названий элементов, для которых следует сохранить пробельные символы. Процедура очистки применяется как для стилей, так и для исходных документов, однако перечень названий элементов, сохраняющих пробельные символы, для стилей и исходных документов определяется отдельно.

Текстовый узел сохраняется если имеет место какое-либо из следующих условий:

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

  • Текстовый узел содержит хотя бы один непробельный символ. Как и в XML, пробельным символом считаются #x20, #x9, #xD и #xA.

  • Элемент, являющийся предком этого текстового узла, имеет атрибут xml:space со значением preserve и нет более близких элементов-предков, имеющих xml:space со значением default.

В остальных случаях текстовый узел вычищается.

Атрибуты xml:space из дерева не вычищаются.

Замечание: Это подразумевает, что если для фиксированного конечного элемента был указан атрибут xml:space, то он будет включен в результат.

В случае со стилями перечень названий элементов, сохраняющих пробельные символы, состоит лишь из xsl:text.

<!-- Category: top-level-element -->
<xsl:strip-space
  elements = tokens />

<!-- Category: top-level-element -->
<xsl:preserve-space
  elements = tokens />

Для исходных документов перечень названий элементов, сохраняющих пробельные символы, задается элементами верхнего уровня xsl:strip-space и xsl:preserve-space. Каждый из этих элементов имеет атрибут elements, значением которого является перечень NameTest-ов (через пробельный символ). Изначально набор названий элементов, сохраняющих пробельные символы, содержит названия всех элементов. Если название элемента совпадает с NameTest в элементе xsl:strip-space, то он удаляется из перечня названий элементов, сохраняющих пробельные символы. Если название элемента совпадает с NameTest в элементе xsl:preserve-space, то оно добавляется к перечню названий элементов, сохраняющих пробельные символы. Элемент соответствует NameTest тогда и только тогда, когда процедура сравнения узлов из XPath для NameTest и этого узла дает результат true. Конфликты между соответствием элементам xsl:strip-space и xsl:preserve-space разрешаются так же как конфликты между правилами шаблона (см. [5.5 Разрешение конфликтов в правилах шаблона]). Таким образом, образец, соответствующий заданному названию элемента, определяется следующим образом:

  • Во-первых, любой образец, имеющий по отношению к другому образцу меньший приоритет импорта, игнорируется.

  • Далее, любой образец с NameTest, который имеет более низкий приоритет по умолчанию, чем приоритет по умолчанию у NameTest для другого образца, игнорируется.

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

4 Выражения

XSLT использует язык выражений, сформулированный в XPath [XPath]. Выражения в XSLT используются для таких целей, как:

  • выбор узлов для обработки;
  • формулирование условий для разных вариантов обработки узла;
  • генерация текста для подстановки в конечное дерево.

Выражение должно соответствовать сценарию Expr из XPath.

Выражения используются в значении определенных атрибутов у элементов, описанных в XSLT, а также - в фигурных скобках - в шаблоне для значения атрибута.

Внешнее выражение в XSLT (т.е. выражение, не являющееся частью какого-либо другого выражения) получает свой контекст следующим образом:

  • узел контекста получается из текущего узла

  • положение в контексте определяется положением текущего узла в текущем наборе узлов, первая позиция имеет индекс 1

  • размер контекста определяется размером текущего набора узлов

  • привязка переменных контекста - это привязка в пределах видимости того элемента, которому принадлежит атрибут с рассматриваемым выражением (см. [11 Переменные и параметры])

  • набор деклараций пространства имен - это те декларации, в области видимости которых находится элемент, содержащий атрибут с рассматриваемым выражением. Сюда относится также неявная декларация префикса xml, обязательная согласно W3C Namespaces Recommendation [XML Names]. Пространство имен по умолчанию (декларируемое в xmlns) к этому набору деклараций не относится

  • используемая библиотека функций формируется из основной библиотеки функций, дополнительных функций, описанных в главе [12 Дополнительные функции], а также функций расширения, описанных в главе [14 Расширения]. Если в выражении появится вызов какой-либо другой функции, зафиксируется ошибка.

5 Правила шаблона

5.1 Схема обработки

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

Реализация XMLT может обрабатывать исходный документ любым способом, который дает тот же результат, как если бы выполнялась обработка в соответствии с представленной моделью.

5.2 Образцы

Правило шаблона идентифицирует узлы, к которым оно будет применяться, с помощью образца. Помимо правил шаблона, образцы используются также для нумерации (см. [7.7 Нумерация]) и декларирования ключей (см. [12.2 Ключи]). Образец задает перечень условий для обрабатываемого узла. Узел, который отвечает этим условиям, шаблону соответствует, а узел, который условиям не отвечает, шаблону не соответствует. Синтаксис шаблонов является подмножеством синтаксиса выражений. В частности, в качестве шаблонов могут использоваться пути адресации, которые отвечают определенным ограничениям. Выражение, которое является образцом, обрабатывается всегда как объект типа "набор узлов". Узел соответствует образцу, если он числится в наборе узлов, полученных в результате обработки этого образца как некого выражения в неком возможном контексте. Возможные контексты - это такие контексты, чей узлом контекста является проверяемый узел или один из его предков.

Некоторые примеры шаблонов:

  • para соответствует любому элементу para

  • * соответствует любому элементу

  • chapter|appendix соответствует любому элементу chapter и любому элементу appendix

  • olist/item соответствует любому элементу item с родителем olist

  • appendix//para соответствует любому элементу para, предком которого является элемент appendix

  • / соответствует корневому узлу

  • text() соответствует любому текстовому узлу

  • processing-instruction() соответствует любой инструкции обработки

  • node() соответствует любому узлу за исключением узла атрибута и корневого узла

  • id("W11") соответствует элементу с уникальным ID W11

  • para[1] соответствует любому элементу para, который для своего родителя будет первым непосредственным потомком являющимся элементом para

  • *[position()=1 and self::para] соответствует любому элементу para, являющемуся для своего родителя первым непосредственным элементом-потомком

  • para[last()=1] соответствует любому элементу para, который является для своего родителя единственным непосредственным потомком para

  • items/item[position()>1] соответствует любому элементу item, который имеет родителя items, но не является для этого родителя первым непосредственным потомком item

  • item[position() mod 2 = 1] будет иметь значение true для любого элемента item, который является нечетным непосредственным потомком item своего родителя.

  • div[@class="appendix"]//p соответствует любому элементу p, предком которого является элемент div, имеющий атрибут class со значением appendix

  • @class соответствует любому атрибуту class (но не любому элементу, имеющему атрибут class)

  • @* соответствует любому атрибуту

Образец должен отвечать грамматике Pattern. Pattern представляет собой набор образцов для путей адресации, разделенных символом |. Образец для пути адресации - это некий путь адресации, на всех шагах которого используются лишь оси child или attribute. Хотя образцы и не должны использовать ось descendant-or-self, в образцах могут использоваться как оператор //, так и оператор /. Образцы путей адресации могут начинаться также с вызова функций id или key с фиксированным аргументом. В предикатах образца могут использоваться произвольные выражения так это происходит в предикатах пути адресации.

Образцы
[1] | Pattern | ::= | LocationPathPattern
 |  |  | | Pattern '|' LocationPathPattern
[2] | LocationPathPattern | ::= | '/' RelativePathPattern?
 |  |  | | IdKeyPattern (('/' | '//') RelativePathPattern)?
 |  |  | | '//'? RelativePathPattern
[3] | IdKeyPattern | ::= | 'id' '(' Literal ')'
 |  |  | | 'key' '(' Literal ',' Literal ')'
[4] | RelativePathPattern | ::= | StepPattern
 |  |  | | RelativePathPattern '/' StepPattern
 |  |  | | RelativePathPattern '//' StepPattern
[5] | StepPattern | ::= | ChildOrAttributeAxisSpecifier NodeTest Predicate*
[6] | ChildOrAttributeAxisSpecifier | ::= | AbbreviatedAxisSpecifier
 |  |  | | ('child' | 'attribute') '::'

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

Например, образец p соответствует любому элементу p, потому что если взять любой элемент p и обработать выражение p, используя в качестве контекста родителя элемента p, то одним из членов полученного набора узлов будет этот элемент p.

Замечание: Такой образец соответствует даже элементу p, являющемуся элементом этого документа, поскольку корень документа является родителем элемента документа.

Хотя семантика образцов формулируется косвенно в терминах обработки выражений, смысл образца легко понять сразу, не прибегая к терминологии обработки выражений. Символ | в образце обозначает альтернативу. Соответствие образцу с одним или несколькими символами |, разделяющими альтернативы, засчитывается если есть соответствие одной из этих альтернатив. Для образца, состоящего из последовательности StepPattern-ов, разделенных / или //, соответствие проверяется справа налево. Соответствие образцу засчитывается только если есть соответствие самому правому StepPattern, а соответствующий элемент отвечает остальной части образца. Если разделителем является /, то таким элементом может быть только родитель, если же разделителем является //, то в качестве такого элемента может использоваться любой из предков. Соответствие StepPattern, использующему ось child, засчитывается если для данного узла NodeTest дает true, а сам узел не является узлом атрибута. Соответствие StepPattern, использующему ось attribute, засчитывается если для данного узла NodeTest дает true, а сам узел является узлом атрибута. Если присутствует [], то в StepPattern сперва обрабатывается PredicateExpr, причем проверяемый узел используется как узел контекста, а в качестве контекстного набора узлов берутся узлы, которые имеют общего родителя с узлом контекста и соответствуют NodeTest. Однако если проверяемый узел является узлом атрибута, то в этом случае контекстный набор узлов - это все атрибуты, имеющие с проверяемым атрибутом общего родителя и соответствующие NameTest.

Например,

appendix//ulist/item[position()=1]

соответствует узлу тогда и только тогда, когда выполняются все следующие условия:

  • NodeTest item дает true для данного узла, а сам узел не является узлом атрибута, иными словами, данный узел является элементом item

  • обработка PredicateExpr position()=1 дает true, если данный узел берется как узел контекста, а набор элементов item, имеющих с ним общего родителя, берется как контекстный набор узлов

  • данный узел имеет родителя, отвечающего условию appendix//ulist, это будет так, если этот родитель является элементом ulist, предком которого является элемент appendix.

5.3 Определение правил шаблона

<!-- Category: top-level-element -->
<xsl:template
  match = pattern
  name = qname
  priority = number
  mode = qname>
  <!-- Content: (xsl:param*, template) -->
</xsl:template>

Правило шаблона задается элементом xsl:template. Атрибут match соответствует образу, который идентифицирует исходные узел или узлы, к которым это правило применяется. Если элемент xsl:template не имеет атрибута name, атрибут match обязателен (см. [6 Именованные шаблоны]). Если в значении атрибута match содержится VariableReference, фиксируется ошибка. Содержимое элемента xsl:template является шаблоном, который обрабатывается если данное правило шаблона задействовано.

Например, документ XML может содержать:

This is an <emph>important</emph> point.

Приведенное далее правило шаблона соответствует элементам emph и создает объект форматирования fo:inline-sequence, имеющий свойство font-weight со значением bold.

<xsl:template match="emph">
  <fo:inline-sequence font-weight="bold">
    <xsl:apply-templates/>
  </fo:inline-sequence>
</xsl:template>
Примечание: В примерах этого документа префикс fo: используется для пространства имен http://www.w3.org/1999/XSL/Format (пространства имен объектов форматирования, определенных в [XSL]).

Как описано далее, элемент xsl:apply-templates рекурсивно обрабатывает непосредственные потомки данного исходного элемента.

5.4 Использование правил шаблона

<!-- Category: instruction -->
<xsl:apply-templates
  select = node-set-expression
  mode = qname>
  <!-- Content: (xsl:sort | xsl:with-param)* -->
</xsl:apply-templates>

В данном примере для элемента chapter создается блок, а затем обрабатывается его непосредственный потомок.

<xsl:template match="chapter">
  <fo:block>
    <xsl:apply-templates/>
  </fo:block>
</xsl:template>

В отсутствие атрибута select инструкция xsl:apply-templates обрабатывает все непосредственные потомки текущего узла, включая узлы текста. Однако те текстовые узлы, которые были вычищены как описано в главе [3.4 Удаление пробельных символов], обрабатываться не будут. Если очистка узлов с пробельными символами для элемента не была разрешена, то все пробельные символы в содержимом этого элемента будут обрабатываться как текст, и, следовательно, пробельный символ между элементами - непосредственными потомками будет учитываться при вычислении положения элемента - непосредственного потомка, возвращаемого функцией position.

Чтобы обрабатывать не все непосредственные потомки, а лишь узлы, отобранные по некому выражению, может использоваться атрибут select. Значением атрибута select является выражение. После обработки этого выражения должен получиться набор узлов. Если нет указаний по сортировке (см. [10 Сортировка]), собранный перечень узлов обрабатывается в том порядке, как они следуют в документе. В следующем примере обрабатываются все непосредственные потомки author для этого элемента author-group:

<xsl:template match="author-group">
  <fo:inline-sequence>
    <xsl:apply-templates select="author"/>
  </fo:inline-sequence>
</xsl:template>

В следующем примере обрабатываются все содержащиеся в author элементы given-name, которые являются непосредственным потомком author-group:

<xsl:template match="author-group">
  <fo:inline-sequence>
    <xsl:apply-templates select="author/given-name"/>
  </fo:inline-sequence>
</xsl:template>

В данном примере обрабатываются все элементы heading, являющиеся потомками элемента book.

<xsl:template match="book">
  <fo:block>
    <xsl:apply-templates select=".//heading"/>
  </fo:block>
</xsl:template>

Есть также возможность обрабатывать элементы, которые не являются потомками текущего узла. В данном примере предполагается, что элемент department имеет непосредственный потомок group и потомки employee. Сперва находится отдел employee, а затем обрабатывается непосредственный потомок group элемента department.

<xsl:template match="employee">
  <fo:block>
    Employee <xsl:apply-templates select="name"/> belongs to group
    <xsl:apply-templates select="ancestor::department/group"/>
  </fo:block>
</xsl:template>

Для выполнения простого переупорядочения в пределах одного шаблона можно использовать сразу несколько элементов xsl:apply-templates. В следующем примере создаются две таблицы HTML. Первая таблица заполняется отечественными продажами, вторая - международными.

<xsl:template match="product">
  <table>
    <xsl:apply-templates select="sales/domestic"/>
  </table>
  <table>
    <xsl:apply-templates select="sales/foreign"/>
  </table>
</xsl:template>
Замечание: Может оказаться, что шаблону соответствуют два потомка, причем один из них является потомком другого. Как-то особенно такой случай не обрабатывается: оба потомка будут обработаны обычным образом. Например, дан исходный документ
<doc><div><div></div></div></doc>
правило
<xsl:template match="doc">
  <xsl:apply-templates select=".//div"/>
</xsl:template>
будет обрабатывать и внешний, и внутренний элементы div.
Замечание: Обычно xsl:apply-templates используется для обработки только тех узлов, которые являются потомками текущего узла. Такое использование xsl:apply-templates не может привести к появлению бесконечных циклов обработки. Однако когда xsl:apply-templates используется для обработки элементов, не являющихся потомками текущего узла, появляется вероятность возникновения бесконечных циклов. Например,
<xsl:template match="foo">
  <xsl:apply-templates select="."/>
</xsl:template>
Реализации процессора в некоторых случаях могут выявить такие циклы, однако остается вероятность, что стиль попадет в такой бесконечный цикл, который эта реализация не сможет обнаружить. Для безопасности это может представлять угрозу типа "отказ в обслуживании".

5.5 Разрешение конфликтов в правилах шаблона

Может оказаться, что исходный узел соответствует сразу нескольким правилам шаблона. Правило шаблона, которое должно использоваться, определяется следующим образом:

  1. Во-первых, из рассмотрения исключаются все соответствующие узлу правила шаблона, которые имеют более низкий приоритет импорта, чем проверяемое правило шаблона и правила с наивысшим приоритетом импорта.

  2. Затем из рассмотрения исключаются все соответствующие узлу правила шаблона, которые имеют более низкий приоритет чем данное соответствующее правило шаблона и правила с наивысшим приоритетом. Приоритет правила шаблона задается атрибутом priority. Значением этого атрибута должно быть реальное число (положительное или отрицательное), соответствующее сценарию Number с необязательным начальным символом минус (-). Приоритет по умолчанию вычисляется следующим образом:

    • Если образец содержит несколько альтернатив, разделенных символом |, то он обрабатывается также как набор из правил шаблона, по одному на каждую из представленных альтернатив.

    • Если образец имеет вид QName, которому предшествует ChildOrAttributeAxisSpecifier, или имеет вид processing-instruction( Literal ), которому предшествует ChildOrAttributeAxisSpecifier, то приоритет считается равным 0.

    • Если образец имеет вид NCName :*, которому предшествует ChildOrAttributeAxisSpecifier, то его приоритет равен -0.25.

    • В противном случае, если образец состоит только из NodeTest, которому предшествует ChildOrAttributeAxisSpecifier, то его приоритет равен -0.5.

    • В остальных случаях приоритет равен 0.5.

    Таким образом, самый общий тип образцов (образец, проверяющий узел определенного типа и с определенным расширенным именем) имеет приоритет 0. Следующий, более общий тип образца (образец, проверяющий узел определенного типа и с расширенным именем и определенным URI пространства имен) имеет приоритет -0.25. Еще более общие образцы (образцы, проверяющие лишь узлы определенных типов) имеют приоритет -0.5. Образцы, еще более специальные, чем самый общий тип образца, имеют приоритет 0.5.

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

5.6 Переопределение правил шаблона

<!-- Category: instruction -->
<xsl:apply-imports />

Правило шаблона, которое должно использоваться для переопределения другого правила шаблона в импортированном стиле (см. [5.5 Разрешение конфликтов в правилах шаблона]), может воспользоваться элементом xsl:apply-imports чтобы вызвать переопределенное правило шаблона.

При обработке стиля в каждой точке имеется некое текущее правило шаблона. Всякий раз, когда по образцу выбирается правило шаблона, для обработки оно становится текущим правилом шаблона. Когда обрабатывается элемент xsl:for-each, то при обработке содержимого этого элемента xsl:for-each текущее правило шаблона становится нулевым.

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

Например, предположим что стиль doc.xsl содержит правило шаблона для элементов example:

<xsl:template match="example">
  <pre><xsl:apply-templates/></pre>
</xsl:template>

Другой стиль может импортировать doc.xsl и поменять обработку элементов example следующим образом:

<xsl:import href="doc.xsl"/>

<xsl:template match="example">
  <div style="border: solid red">
     <xsl:apply-imports/>
  </div>
</xsl:template>

В результате суммарного действия example должен преобразовываться в элемент следующего вида:

<div style="border: solid red"><pre>...</pre></div>

5.7 Режимы

Режимы позволяют обрабатывать элемент несколько раз, получая каждый раз другой результат.

Оба элемента xsl:template и xsl:apply-templates имеют необязательный атрибут mode. Значением атрибута mode является название QName, которое приводится к расширенному имени как было описано в главе [2.4 Полные имена]. Если xsl:template не имеет атрибута match, то он не должен иметь и атрибута mode. Если элемент xsl:apply-templates имеет атрибут mode, то он применяется только к тем правилам шаблона из элементов xsl:template, которые имеют атрибут mode с тем же значением. Если элемент xsl:apply-templates атрибута mode не имеет, то он применяется только к тем правилам шаблона из элементов xsl:template, которые также не имеют атрибута mode.

5.8 Встроенные правила шаблона

Имеется встроенное правило шаблона, позволяющее рекурсивно продолжать обработку в отсутствии успешного сравнения с явным правилом шаблона в стиле. Это правило шаблона используется как для узлов элементов, так и для корневого узла. Далее приведен эквивалент встроенного правила шаблона:

<xsl:template match="*|/">
  <xsl:apply-templates/>
</xsl:template>

Для каждого метода также есть встроенное правило шаблона, позволяющее рекурсивно продолжать обработку в том же самом режиме, в отсутствии успешного сравнения с образцом из явного правила шаблона в этом стиле. Это правило шаблона применяется как для узлов элементов, так и для корневого узла. Далее приведен эквивалент встроенного правила шаблона для режима m.

<xsl:template match="*|/" mode="m">
  <xsl:apply-templates mode="m"/>
</xsl:template>

Также есть встроенное правило шаблона для текстовых узлов и узлов атрибутов, которое просто копирует текст:

<xsl:template match="text()|@*">
  <xsl:value-of select="."/>
</xsl:template>

Для инструкций обработки и комментариев встроенное правило шаблона не должно делать ничего.

<xsl:template match="processing-instruction()|comment()"/>

Встроенное правило шаблона для узлов пространства имен также не должно делать ничего. Нет образца, который бы мог соответствовать узлу пространства имен, поэтому встроенное правило шаблона является единственным правилом шаблона, которое применяется к узлам пространства имен.

Встроенные правила шаблона обрабатываются так, как будто они были неявно импортированы прежде стиля, а потому имеют меньший приоритет импорта, чем все остальные правила шаблона. Таким образом, автор может переопределить встроенное правило шаблона, явно включив новое правило шаблона.

6 Именованные шаблоны

<!-- Category: instruction -->
<xsl:call-template
  name = qname>
  <!-- Content: xsl:with-param* -->
</xsl:call-template>

Шаблоны можно вызывать по имени. Именованный шаблон задается элементом xsl:template с атрибутом name. Значением атрибута является имя name QName, которое приводится к расширенному имени как описано в главе [2.4 Полные имена]. Если элемент xsl:template имеет атрибут name, то он может, но не обязан, иметь также атрибут match. Элемент xsl:call-template вызывает шаблон по имени, он содержит обязательный атрибут name, идентифицирующий шаблон, который должен быть вызван. В отличие от xsl:apply-templates, xsl:call-template не меняет текущий узел и текущий набор узлов.

Атрибуты match, mode и priority в элементе xsl:template не зависят от того, был ли этот шаблон вызван элементом xsl:call-template. Точно так же атрибут nameв элементе xsl:template не зависит от того, был ли этот шаблон вызван элементом xsl:apply-templates.

Если стиль содержит более одного шаблона с одним и тем же названием, а также одним и тем же приоритетом импорта, фиксируется ошибка.

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 пространства имен. Это относится к:

  • 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 узлов, не являющихся текстовыми. Реализации процессора могут либо сигнализировать об этой ошибке, либо просто игнорировать неправильные узлы.

Замечание: Если 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 как-либо особо. Например,

  • автор стиля непосредственно отвечает за генерацию всех атрибутов xml:lang и xml:space, которые необходимы в результате;

  • появление атрибута xml:lang или xml:space в элементе из пространства имен XSLT не приводит к появлению атрибутов xml:lang или xml:space в конечном материале.

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 расставляет числа в зависимости от позиции текущего узла в исходном дереве. Следующие атрибуты определяют, как должен нумероваться текущий узел:

  • Атрибут level определяет, какие уровни исходного дерева следует рассматривать. Он имеет значения single, multiple или any. По умолчанию используется single.

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

  • Атрибут from является образцом, указывающим, где начинается счет.

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

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

  • Если задано level="single", на оси ancesor-or-self берется первый узел, соответствующий образцу count, и строится список длиною единица, содержащий один плюс число узлов, которые соответствуют образцу count, предшествующих данному предку и имеют с ним общего родителя. Если такого предка нет, создается пустой список. Если указан атрибут from, то ищутся лишь те предки, которые являются потомками ближайшего предка, соответствующего образцу from. В этом случае предшествующие узлы, имеющие общего родителя, те же самые как при использовании оси preceding-sibling.

  • Если указано level="multiple", то создается перечень всех предков текущего узла в том порядке, как они встречаются в документе, а список завершает сам этот элемент. Затем из этого перечня выбираются узлы соответствующие образцу count. И, наконец, каждый узел в этом списке замещается единицей плюс количество предшествующих узлов, имеющих того же родителя и соответствующих образцу count. Если указан атрибут from, то ищутся лишь те предки, которые являются потомками ближайшего предка, соответствующего образцу from. Предшествующие узлы, имеющие того же родителя - те же самые как при использовании оси preceding-sibling.

  • Если указано level="any", то создается список единичной длины, содержащий количество узлов, которые соответствуют образцу count и принадлежат набору из текущего узла и всех узлов на всех уровнях документа, предшествующих в документе текущему узлу, за исключением всех узлов атрибутов и пространства имен (иными словами, объединенному множеству членов на осях preceding и ancestor-or-self). Если указан атрибут from, то после первого узла рассматриваются только те узлы, предшествующие текущему узлу, которые соответствуют образцу 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 и интерпретируются следующим образом:

  • Любая лексема, где последний символ имеет значение десятичной цифры 1 (указанное в базе данных по свойствам символов Unicode), а значение Unicode предшествующих символов меньше чем значение Unicode последнего символа, генерирует такое десятичное представление числа, что любое число будет не короче лексемы форматирования. Так, лексема форматирования 1 генерирует последовательность 1 2 ... 10 11 12 ..., а лексема форматирования 01 дает последовательность 01 02 ... 09 10 11 12 ... 99 100 101.

  • Лексема форматирования A генерирует последовательность A B C ... Z AA AB AC....

  • Лексема форматирования a генерирует последовательность a b c ... z aa ab ac....

  • Лексема форматирования i генерирует последовательность i ii iii iv v vi vii viii ix x ....

  • Лексема форматирования I генерирует последовательность I II III IV V VI VII VIII IX X ....

  • Любая другая лексема форматирования задает последовательность нумерации, которая начинается с указанной лексемы. Если реализация процессора не поддерживает последовательность нумерации, начинающуюся с этой лексемы, должна использоваться лексема форматирования 1.

Если нумерация выполняется последовательностью букв, атрибут 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, он игнорируется.

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

  • format="&#x30A2;" задает нумерацию Katakana

  • format="&#x30A4;" задает нумерацию Katakana в последовательности "iroha"

  • format="&#x0E51;" задает нумерацию тайскими цифрами

  • format="&#x05D0;" letter-value="traditional" задает "традиционную" еврейскую нумерацию

  • format="&#x10D0;" letter-value="traditional" задает григорианскую нумерацию

  • format="&#x03B1;" letter-value="traditional" задает "классическую" греческую нумерацию

  • format="&#x0430;" letter-value="traditional" задает старославянскую нумерацию

8 Повторение

<!-- Category: instruction -->
<xsl:for-each
  select = node-set-expression>
  <!-- Content: (xsl:sort*, template) -->
</xsl:for-each>

Если результат имеет известную регулярную структуру, полезно иметь возможность указать это прямо в шаблоне для собираемых узлов. Инструкция xsl:for-each содержит шаблон, который обрабатывается для каждого узла, отобранного выражением, указанным в атрибуте select. Атрибут select является обязательным. Результатом обработки выражения должен быть набор узлов. При обработке шаблона выбранный узел берется в качестве текущего узла, а весь список собранных узлов берется в качестве текущего набора узлов. Узлы обрабатываются в том порядке как они следуют в документе, если нет указаний относительно сортировки (см. [10 Сортировка]).

Например, дан XML документ со следующей структурой

<customers>
  <customer>
    <name>...</name>
    <order>...</order>
    <order>...</order>
  </customer>
  <customer>
    <name>...</name>
    <order>...</order>
    <order>...</order>
  </customer>
</customers>

Следующий пример должен создать HTML документ, содержащий таблицу, где каждому элементу customer отводится отдельная строка.

<xsl:template match="/">
  <html>
    <head>
      <title>Customers</title>
    </head>
    <body>
      <table>
    <tbody>
      <xsl:for-each select="customers/customer">
        <tr>
          <th>
        <xsl:apply-templates select="name"/>
          </th>
          <xsl:for-each select="order">
        <td>
          <xsl:apply-templates/>
        </td>
          </xsl:for-each>
        </tr>
      </xsl:for-each>
    </tbody>
      </table>
    </body>
  </html>
</xsl:template>

9 Обработка с условием

В XSLT в шаблоне обработку с условием поддерживают две инструкции: xsl:if и xsl:choose. Инструкция xsl:if дает простую функциональность if-then, инструкция xsl:choose поддерживает выбор одного из нескольких возможных вариантов.

9.1 Обработка с условием xsl:if

<!-- Category: instruction -->
<xsl:if
  test = boolean-expression>
  <!-- Content: template -->
</xsl:if>

Элемент xsl:if имеет атрибут test, который определяет некое выражение. Содержимое элемента является шаблоном. Указанное выражение обрабатывается, а полученный объект преобразуется в булево значение как при вызове функции boolean. Если результатом является true, то подставляется шаблон, имеющийся в выражении. В противном случае не создается ничего. В следующем примере группа имен оформляется в виде списка через запятую:

<xsl:template match="namelist/name">
  <xsl:apply-templates/>
  <xsl:if test="not(position()=last())">, </xsl:if>
</xsl:template>

В следующем примере каждый второй ряд таблицы раскрашивается желтым:

<xsl:template match="item">
  <tr>
    <xsl:if test="position() mod 2 = 0">
       <xsl:attribute name="bgcolor">yellow</xsl:attribute>
    </xsl:if>
    <xsl:apply-templates/>
  </tr>
</xsl:template>

9.2 Обработка с условием xsl:choose

<!-- Category: instruction -->
<xsl:choose>
  <!-- Content: (xsl:when+, xsl:otherwise?) -->
</xsl:choose>

<xsl:when
  test = boolean-expression>
  <!-- Content: template -->
</xsl:when>

<xsl:otherwise>
  <!-- Content: template -->
</xsl:otherwise>

Среди нескольких возможных альтернатив элемент xsl:choose выбирает одну. Он состоит из последовательности элементов xsl:when, за которой следует необязательный элемент xsl:otherwise. Каждый элемент xsl:when имеет единственный атрибут test, который задает некое выражение. Содержимое элементов xsl:when и xsl:otherwise является шаблоном. Если обрабатывается элемент xsl:choose, поочередно проверяются все элементы xsl:when. При этом обрабатывается соответствующее выражение, а полученный объект преобразуется в булевый тип как при вызове функции boolean. Обрабатывается содержимое первого, и только первого элемента xsl:when, при проверке которого было получено true. Если ни один из xsl:when не показал true, подставляется значение элемента xsl:otherwise. Если ни один из xsl:when не показал true, а элемент xsl:otherwise отсутствует, то ничего не создается.

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

<xsl:template match="orderedlist/listitem">
  <fo:list-item indent-start='2pi'>
    <fo:list-item-label>
      <xsl:variable name="level"
                    select="count(ancestor::orderedlist) mod 3"/>
      <xsl:choose>
        <xsl:when test='$level=1'>
          <xsl:number format="i"/>
        </xsl:when>
        <xsl:when test='$level=2'>
          <xsl:number format="a"/>
        </xsl:when>
        <xsl:otherwise>
          <xsl:number format="1"/>
        </xsl:otherwise>
      </xsl:choose>
      <xsl:text>. </xsl:text>
    </fo:list-item-label>
    <fo:list-item-body>
      <xsl:apply-templates/>
    </fo:list-item-body>
  </fo:list-item>
</xsl:template>

10 Сортировка

<xsl:sort
select =
string-expression
lang = { nmtoken
}
data-type = { "text" | "number" |
qname-but-not-ncname }
order = { "ascending" |
"descending" }
case-order = { "upper-first" | "lower-first"
} />

Сортировка задается с помощью элементов xsl:sort, данных как непосредственный потомок элемента xsl:apply-templates или xsl:for-each. Первый непосредственный потомок xsl:sort задает первичный ключ сортировки, второй непосредственный потомок xsl:sort задает вторичный ключ сортировки, и так далее. Если элемент xsl:apply-templates или xsl:for-each имеет одного или несколько непосредственных потомков xsl:sort, то вместо того чтобы обрабатывать выбранные узлы в том порядке как они следуют в документе, сперва производится их упорядочение в соответствии с заданными ключами сортировки, и лишь затем они обрабатываются в полученном порядке. При использовании в xsl:for-each элементы xsl:sort должны ставиться в начале. Если обрабатывается шаблон из xsl:apply-templates и xsl:for-each, то в качестве текущего набора узлов берется полный отсортированный список обрабатываемых узлов.

xsl:sort имеет атрибут select, значением которого является выражение. Указанное выражение вычисляется для каждого узла, подлежащего обработке. При этом данный узел используется в качестве текущего узла, а полный неупорядоченный список узлов, подлежащих обработке, выступает в роли текущего набора узлов. Полученный после вычисления объект преобразуется в строку как при вызове функции string. Данная строка используется как ключ сортировки для этого узла. По умолчанию атрибут select имеет значение ., которое приводит к тому, что в качестве ключа сортировки используется строковое значение текущего узла.

Полученная строка используется как ключ сортировки для данного узла. Ниже приведены необязательные атрибуты элемента xsl:sort, управляющие упорядочением списка ключей сортировки, значения всех этих атрибутов рассматриваются как шаблон значения атрибута.

  • order определяет, следует ли сортировать строки в направлении к предкам или потомкам. ascending определяет порядок в направлении к предкам. descending определяет порядок сортировки в направлении к потомкам. По умолчанию подразумевается ascending

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

  • data-type определяет тип данных для данных строк, разрешены следующие значения:

    • text указывает, что ключи сортировки должны быть упорядочены лексически в соответствии с культурными особенностями языка, указанного в атрибуте lang

    • number указывает что ключи сортировки должны быть преобразованы в числа, а затем упорядочены в соответствии со своим числовым значением, ключ сортировки преобразуется в число как при вызове функции number, атрибут lang игнорируется

    • QName с префиксом преобразуется в расширенное имя как описано в главе [2.4 Полные имена]. Расширенное имя идентифицирует тип данных. Данный документ не конкретизирует действия, предпринимаемые в этом случае.

    Значение по умолчанию - text.

    Замечание: Рабочая группа XSL планирует, что будущие версии XSLT будут использовать схемы XML для определения других значений для этого атрибута.

  • case-order имеет значение upper-first или lower-first. Данный атрибут используется когда есть data-type="text" и указано что заглавные буквы должны ставиться прежде прописных, либо, соответственно, наоборот. Например, если есть lang="en", то последовательность A a B b получается после сортировки с case-order="upper-first", а a A b B - после case-order="lower-first". Значение по умолчанию зависит от языка.

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

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

К примеру, предположим, что база данных служащих имеет формат

<employees>
  <employee>
    <name>
      <given>James</given>
      <family>Clark</family>
     </name>
    ...

  </employee>
</employees>

в таком случае список служащих можно отсортировать по имени с помощью:

<xsl:template match="employees">
  <ul>
    <xsl:apply-templates select="employee">
      <xsl:sort select="name/family"/>
      <xsl:sort select="name/given"/>
    </xsl:apply-templates>
  </ul>
 </xsl:template>

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

11 Переменные и параметры

<!-- Category: top-level-element -->
<!-- Category: instruction -->
<xsl:variable
  name = qname
  select = expression>
  <!-- Content: template -->
</xsl:variable>

<!-- Category: top-level-element -->
<xsl:param
  name = qname
  select = expression>
  <!-- Content: template -->
</xsl:param>

Переменная - это имя, которое может быть связано со значением. Значение, к которому привязана переменная, (значение переменной) может быть объектом любого типа, который может быть возвращен выражением. Для привязки переменных могут использоваться два элемента: xsl:variable и xsl:param. Разница между ними заключается в том, что значение, указанное в переменной xsl:param, является лишь значением по умолчанию. Если используется шаблон или стиль, в котором используется элемент xsl:param, то могут быть переданы параметры, которые будут использоваться вместо значений по умолчанию.

И xsl:variable, и xsl:param имеют обязательный атрибут name, задающий имя переменной. Значением атрибута name является QName, которое приводится к расширенному имени как описано в главе [2.4 Полные имена].

Когда используется любой из этих элементов привязки переменных, в дереве стилей всегда есть область, где эта привязка будет видима. В пределах этой области видима любая привязка данной переменной, однако соответствующий элемент привязки переменной остается скрытым. Таким образом, видна только самая внутренняя привязка переменной. Набор привязок переменной в области видимости выражения состоит из тех привязок, которые были видимы в том месте стиля, где это выражение находится.

11.1 Фрагменты конечного дерева

Переменные привносят в язык выражений новый тип данных. Этот дополнительный тип данных называется фрагментом конечного дерева (result tree fragment). Переменная может быть привязана к фрагменту конечного дерева, а не только к одному из четырех базовых типов данных в XPath (строка, число, булево значение, набор узлов). Фрагмент конечного дерева представляет здесь именно фрагмент в конечном дереве. Фрагмент конечного дерева обрабатывается точно так же как набор узлов, который содержит только один корневой узел. Однако для фрагмента конечного дерева разрешена лишь часть операций, допустимых для набора узлов. Операцию можно использовать для фрагмента конечного дерева только когда ее можно использовать для строки (операция над строкой может включать предварительное преобразование этой строки в число или булево значение). В частности, для фрагментов конечного дерева нельзя использовать операции /, // и []. Если для фрагмента конечного дерева выполняется рпазрешенная операция, то она выполняется точно так же как если применена к эквивалентному набору узлов.

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

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

11.2 Значения переменных и параметров

Элемент привязки переменной может указывать значение переменной тремя разными способами.

  • Если элемент привязки переменной имеет атрибут select, то значением этого атрибута должно быть выражение, а значением самой переменной является объект, полученный в результате обработки этого выражения. Содержимое элемента в этом случае должно быть пустым.

  • Если элемент привязки переменной не имеет атрибута select, но имеет непустое содержание (иначе говоря, элемент привязки переменной имеет один или несколько узлов - непосредственных потомков), тогда требуемое значение задается содержимым элемента привязки переменной. Содержимое элемента привязки переменной является шаблоном, который обрабатывается для получения значения данной переменной. Этим значением является фрагмент конечного дерева, эквивалентный набору узлов, состоящему из одного корневого узла, который в качестве непосредственных потомков имеет последовательность узлов, полученных при обработке представленного шаблона. Базовым URI для узлов в рассматриваемом фрагменте конечного дерева является базовый URI элемента привязки переменной.

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

  • Если элемент привязки переменной имеет пустое содержание и не имеет атрибута select, значением переменной является пустая строка. Таким образом

    <xsl:variable name="x"/>

    равнозначно

    <xsl:variable name="x" select="''"/>
Замечание: Если переменная используется для нахождения узла по номеру позиции, то не следует делать следующего:
<xsl:variable name="n">2</xsl:variable>
...
<xsl:value-of select="item[$n]"/>
Результатом будет значение первого элемента item, поскольку переменная n будет привязана к фрагменту конечного дерева, а не к числу. Вместо этого делайте либо
<xsl:variable name="n" select="2"/>
...
<xsl:value-of select="item[$n]"/>
либо
<xsl:variable name="n">2</xsl:variable>
...
<xsl:value-of select="item[position()=$n]"/>
Замечание: Удобный прием, позволяющий задать пустой набор узлов в качестве значение по умолчанию для параметра:
<xsl:param name="x" select="/.."/>

11.3 Использование значений переменных и параметров с конструкцией xsl:copy-of

<!-- Category: instruction -->
<xsl:copy-of
  select = expression />

Чтобы вставить фрагмент конечного дерева в конечное дерево без предварительного преобразования в строку, как это делает xsl:value-of (см. [7.6.1 Создание текста с помощью xsl:value-of]), можно использовать элемент xsl:copy-of. Обязательный атрибут select содержит выражение. Если результатом обработки выражения является фрагмент конечного дерева, то этот фрагмент целиком копируется в конечное дерево. Если же результатом является набор узлов, в конечное дерево копируются все узлы этого набора и в том порядке, как они были в документе. Когда копируется узел элемента, вместе с самим узлом элемента копируются также узлы атрибутов, узлы пространства имен и непосредственные потомки этого узла элемента. Копирование корневого узла выполняется копированием его непосредственных потомков. Если результат не является ни набором узлов, ни фрагментом конечного дерева, то он преобразуется в строку, а затем помещается в конечное дерево, как при использовании xsl:value-of.

11.4 Переменные и параметры верхнего уровня

И xsl:variable, и xsl:param можно использовать в элементах верхнего уровня. Элемент привязки переменной на верхнем уровне декларирует глобальную переменную, которая видна отовсюду. Элемент верхнего уровня xsl:param декларирует параметр для стиля, однако XSLT не определяет механизм передачи параметров стилю. Если стиль содержит привязку для нескольких переменных верхнего уровня с одним и тем же именем и одинаковым приоритетом импорта, фиксируется ошибка. На верхнем уровне выражение или шаблон, указывающие значение переменной, обрабатываются с тем же контекстом, что и при обработке корневого узла в исходном документе: текущим узлом является корневой узел исходного документа, а текущим набором узлов - список, содержащий только корневой узел исходного документа. Если шаблон или выражение, определяющее значение глобальной переменной x, ссылается на глобальную переменную y, то значение y должны быть вычислено прежде значения x. Если это можно сделать не для всех глобальных деклараций переменных, фиксируется ошибка. Иными словами, фиксируется ошибка, если декларации зацикливаются.

Данный пример декларирует глобальную переменную para-font-size, с помощью которой в шаблоне значения атрибута делается ссылка.

<xsl:variable name="para-font-size">12pt</xsl:variable>

<xsl:template match="para">
 <fo:block font-size="{$para-font-size}">
   <xsl:apply-templates/>
 </fo:block>
</xsl:template>

11.5 Переменные и параметры в шаблонах

Помимо верхнего уровня, и xsl:variable, и xsl:param можно использовать также в шаблонах. xsl:variable можно ставить в любом месте шаблона, где допустимо использование инструкций. В этом случае, данная привязка видна для всех последующих узлов, имеющих того же родителя и их потомков. Заметим однако, что привязка для самого элемента xsl:variable не видна. xsl:param можно использовать как непосредственный потомок в начале элемента xsl:template. В данном контексте привязка переменной видна для всех последующих узлов, имеющих того же родителя и их потомков. Заметим, что для самого элемента xsl:param эта привязка не видна.

Одна привязка переменной маскирует другую, если она появляется в точке, где вторая привязка была видна и обе они имеют одно и то же имя. Если привязка переменной, задаваемая в шаблоне элементом xsl:variable или xsl:param, маскируется другой привязкой, заданной в том же шаблоне элементом xsl:variable или xsl:param, фиксируется ошибка. Однако если привязка переменной, заданная в шаблоне элементом xsl:variable или xsl:param, маскирует другую привязку, заданную элементом верхнего уровня xsl:variable или xsl:param, ошибка не фиксируется. Таким образом, в следующем примере содержится ошибка:

<xsl:template name="foo">
<xsl:param name="x" select="1"/>
<xsl:variable name="x" select="2"/>
</xsl:template>

Однако допустим другой вариант:

<xsl:param name="x" select="1"/>
<xsl:template name="foo">
<xsl:variable name="x" select="2"/>
</xsl:template>
Замечание: В Java ближайшим эквивалентом элемента xsl:variable в шаблоне является декларация переменной типа final local с инициализацией. Например,
<xsl:variable name="x" select="'value'"/>
имеет семантику, похожую на
final Object x = "value";
В XSLT нет эквивалента оператору присвоения из Java
x = "value";
поскольку это затруднило бы реализацию процессора, который бы обрабатывал документ не в пакетном режиме, то есть, последовательно от начала до конца.

11.6 Передача параметров шаблону

<xsl:with-param
  name = qname
  select = expression>
  <!-- Content: template -->
</xsl:with-param>

Параметры передаются шаблонам с помощью элемента xsl:with-param. Обязательный атрибут name сообщает название параметра (переменной, значение которой должно быть изменено). Значением атрибута name является QName, процедура приведения которого к расширенному имени описана в главе [2.4 Полные имена]. xsl:with-param можно использовать для xsl:call-template и для xsl:apply-templates. Значение параметра задается точно так же, как для xsl:variable или xsl:param. При обработке значения, заданного элементом xsl:with-param, используются те же текущий узел и текущий набор узлов, что и для элементов xsl:apply-templates или xsl:call-template, в которых этот элемент находится. Если параметр x был передан в шаблон, не имеющий соответствующего элемента xsl:param, ошибка фиксироваться не будет, а сам параметр просто игнорируется.

В данном примере определяется именованный шаблон numbered-block с аргументом, задающий формат числа.

<xsl:template name="numbered-block">
  <xsl:param name="format">1. </xsl:param>
  <fo:block>
    <xsl:number format="{$format}"/>
    <xsl:apply-templates/>
  </fo:block>
</xsl:template>

<xsl:template match="ol//ol/li">
  <xsl:call-template name="numbered-block">
    <xsl:with-param name="format">a. </xsl:with-param>
  </xsl:call-template>
</xsl:template>

12 Дополнительные функции

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

12.1 Множественные исходные документы

Функция: набор-узлов document(объект, набор-узлов?)

Функция document позволяет получить доступ к иным XML-документам помимо основного исходного документа.

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

Если первый аргумент функции document не был набором узлов, он преобразуется в строку как при вызове функции string. Полученная строка обрабатывается как ссылка URI, то есть, извлекается ресурс, идентифицируемый этим URI. Полученные таким образом данные обрабатываются как XML документ и в соответствии с моделью данных (см. [3 Модель данных]) строится дерево. Если при извлечении ресурса произошла ошибка, XSLT процессор может сигнализировать о ней. Если он этого не делает, то должен обработать ошибку сам, возвратив пустой набор узлов. Один из возможных типов ошибки извлечения ресурса связан с тем, что XSLT процессор не поддерживает схему, используемую данным URI. XSLT процессор не обязан поддерживать все возможные схемы URI. В документации для XSLT процессора должно быть указано, какие схемы URI поддерживаются этим процессором.

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

  • Идентификатор фрагмента определяет нечто, чего нельзя представить в виде набора узлов XSLT (например, диапазон символов в текстовом узле).

  • XSLT процессор не поддерживает идентификаторы фрагмента для типа среды, соответствующего полученному результату. XSLT процессор не обязан поддерживать все типы среды, которые могут существовать. В документации к XSLT процессору должно быть указано, для каких типов сред процессор поддерживает идентификаторы фрагментов.

Данные, полученные в результате извлечения, обрабатываются как XML документ независимо от типа среды у результата извлечения. Если типом среды верхнего уровня является text, то он обрабатывается точно так же, как если бы тип среды был text/xml. В противном случае обработка производится так, как если бы тип среды был application/xml.

Замечание: Поскольку для верхнего уровня нет типа среды xml, данные с иным типом среды, чем text/xml или application/xml действительно могут быть XML.

Ссылка URI может быть относительной. Из набора узлов, представленного во втором аргументе, берется узел, который первым встретится в документе, и его базовый URI (см. [3.2 Базовый URI]) используется для преобразования относительных URI в абсолютные. Если второй аргумент опущен, то по умолчанию используется тот узел из стиля, который содержит выражение, включающее рассматриваемый вызов функции document. Заметим, что ссылка URI нулевой длины является ссылкой на документ, относительно которого эта ссылка URI разрешается. Таким образом, document("") ссылается на корневой узел данного стиля, а представление стиля в виде дерева в точности такое же как если бы в качестве исходного документа был взят XML документ, изначально содержащий этот стиль.

Если два документа идентифицируются одним и тем же URI, то они обрабатываются как один и тот же документ. Для сравнения используется абсолютный URI, к каковому приводится любой относительный URI, не содержащий каких-либо идентификаторов фрагментов. Два корневых узла обрабатываются как один и тот же узел, если оба взяты из одного и того же документа. Таким образом, следующее выражение всегда будет давать true:

generate-id(document("foo.xml"))=generate-id(document("foo.xml"))

Функция document дает возможность держать в одном наборе узлов узлы сразу из нескольких документов. Для такого набора узлов относительный порядок следования двух узлов, взятых из одного и того же документа - это обычный порядок следования в документе, заданный в XPath [XPath]. Относительный порядок следования двух узлов из различных документов определяется тем, как реализовано упорядочение документов, содержащих эти узлы. Помимо согласованности (для одного и того же набора документов реализация всегда должна давать один и тот же порядок следования) каких-либо иных ограничений на реализацию упорядочения документов нет.

12.2 Ключи

Ключи дают возможность работать с документами, имеющими неявную структуру перекрестных ссылок. В XML атрибуты типа ID, IDREF и IDREFS создают механизм, позволяющий делать в документах XML перекрестные ссылки явными. В XSLT этот механизм реализуется с помощью функции id из XPath. Однако этот механизм имеет ряд ограничений:

  • Атрибуты ID должны быть декларированы в качестве таковых в DTD. Если атрибут ID декларирован в качестве такового лишь во внешнем наборе DTD, то и распознаваться как ID атрибут он будет только тогда, когда процессор XML прочтет этот внешний набор DTD. Однако спецификация XML вовсе не обязует XML процессоры читать этот внешний DTD, а потому процессоры вполне могут этого не делать, особенно если для документа было декларировано standalone="yes".

  • Документ может иметь только один набор уникальных ID. Не может быть несколько независимых наборов уникальных атрибутов ID.

  • ID элемента может быть задано лишь в атрибуте. Он не может быть задан ни содержимым элемента, ни элементом, являющимся непосредственным потомком.

  • ID должен быть именем XML. Например, он не может содержать пробелов.

  • Элемент может содержать не более одного ID.

  • Любой конкретный ID может принадлежать только одному элементу.

Из-за этих ограничений документы XML иногда имеют структуру перекрестных ссылок, которая не была явно декларирована атрибутами ID/IDREF/IDREFS.

Ключ определяется тремя параметрами:

  1. узлом, которому принадлежит этот ключ

  2. названием ключа (расширенное имя)

  3. значением ключа (строка)

Набор ключей для каждого документа декларируется в стиле с помощью элемента xsl:key. Если в данном наборе ключей есть член с узлом x, названием y и значением z, то мы говорим, что узел x имеет ключ с названием y и значением z.

Таким образом, ключ - это такой тип обобщенного ID, на который не распространяются ограничения, принятые для ID в XML:

  • Ключи декларируются в стиле с помощью элементов xsl:key.

  • Ключи имеют как название, так и значение. Каждое название ключа можно рассматривать как отдельное, независимое пространство идентификаторов.

  • Для элемента значение именованного ключа можно указать в любом удобном месте, например, в содержимом самого элемента, в атрибуте или элементе, являющемся непосредственным потомком. Место, где следует искать значение конкретного именованного ключа, задается выражением XPath.

  • Значением ключа может быть произвольная строка и это не обязательно должно быть имя.

  • В документе может быть несколько ключей, относящихся к одному и тому же узлу и имеющих одно и то же название, но с различными значениями ключа.

  • В документе может быть несколько ключей, имеющих одно и то же название ключа, одно и то же значение, но относящихся к различным узлам.

<!-- Category: top-level-element -->
<xsl:key
  name = qname
  match = pattern
  use = expression />

Чтобы декларировать ключи, используется элемент xsl:key. Название создаваемого ключа задает атрибут name. Значением атрибута name является QName, которое приводится к расширенному имени как было описано в главе [2.4 Полные имена]. Атрибут match является шаблоном. Элемент xsl:key дает информацию о ключах во всех узлах, которые соответствуют шаблону, заданному атрибутом match. Атрибут use дает выражение, определяющее значение ключа. Для каждого узла, соответствующего шаблону, это выражение вычисляется отдельно. Если результатом вычисления является набор узлов, то для каждого узла в этом наборе считается, что узлы, соответствующие представленному шаблону, имеют ключ с указанным именем, значением которого является строковое значение данного узла из набора. В противном случае, результат вычисления преобразуется в строку, и соответствующий шаблону узел получает ключ с указанным названием и значением, соответствующим этой строке. Таким образом, узел x имеет ключ с названием y и значением z тогда и только тогда, когда имеется элемент xsl:key, такой что:

  • x соответствует шаблону, указанному в атрибуте match данного элемента xsl:key,

  • атрибут name элемента xsl:key имеет значение, равное y, и

  • если выражение, заданное атрибутом use элемента xsl:key, обрабатывается с текущим узлом x, а в качестве текущего набора узлов используется список, состоящий из одного x, и при этом результатом является объект u, то либо z равно результату преобразования объекта u в строку (как при вызове функции string), либо u - это набор узлов, а z равно строковому значению одного или нескольких узлов из набора u.

Заметим также, что одному узлу может соответствовать несколько элементов xsl:key. В этом случае будут использованы все совпавшие элементы xsl:key, даже если они имеют разный приоритет импорта.

Если значение атрибутов use или match содержит VariableReference, фиксируется ошибка.

Функция: набор-узлов key(строка, объект)

Функция id играет для ключей ту же роль, что и функция key для идентификаторов ID. Первый аргумент функции указывает имя ключа. Значением данного аргумента должно быть QName, которое приводится к расширеному имени как было описано в главе [2.4 Полные имена]. Если вторым аргументом функции key является список узлов, то результатом вызова будет объединение результатов вызова функции key для строкового значения каждого узла в списке, указанном в аргументе. Если же второй аргумент функции key имеет какой-либо иной тип, то этот аргумент преобразуется в строку, как при вызове функции string. При этом функция возвращает набор узлов из того же документа, где находится узел контекста, значение именованного ключа которых соответствует этой строке.

Например, дана декларация

<xsl:key name="idkey" match="div" use="@id"/>

выражение key("idkey",@ref) возвратит тот же набор узлов, что и id(@ref), при условии, что в исходном XML-документе был декларирован единственный атрибут ID:

<!ATTLIST div id ID #IMPLIED>

а атрибут ref текущего узла не содержит пробельных символов.

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

<prototype name="key" return-type="node-set">
<arg type="string"/>
<arg type="object"/>
</prototype>

а чтобы обратиться к названию функции используется элемент function

<function>key</function>

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

<xsl:key name="func" match="prototype" use="@name"/>
 <xsl:template match="function">
 <b>
  <a href="#{generate-id(key('func',.))}">
    <xsl:apply-templates/>
  </a>
 </b>
 </xsl:template>

<xsl:template match="prototype">
<p><a name="{generate-id()}">
<b>Function: </b>
...
</a></p>
</xsl:template>

Функция key может использоваться для извлечения ключа из других документов, нежели тот, в котором содержится текущий узел контекста. Предположим, к примеру, что документ содержит библиографические ссылки в формате <bibref>XSLT</bibref>, а также есть отдельный XML-документ bib.xml, содержащий библиографическую базу данных с записями в формате:

<entry name="XSLT">...</entry>

В этом случае в стиле можно использовать следующий вариант преобразования элементов bibref:

<xsl:key name="bib" match="entry" use="@name"/>

<xsl:template match="bibref">
  <xsl:variable name="name" select="."/>
  <xsl:for-each select="document('bib.xml')">
    <xsl:apply-templates select="key('bib',$name)"/>
  </xsl:for-each>
</xsl:template>

12.3 Форматирование чисел

Функция: строка format-number(число, строка, строка?)

Функция format-number преобразует свой первый аргумент в строку, используя строку шаблона форматирования, представленную во втором аргументе, и десятичный формат, поименованый в третьем аргументе, либо десятичный формат по умолчанию, если третий аргумент отсутствует. Строка с шаблоном форматирования имеет синтаксис, определенный в JDK 1.1 для класса DecimalFormat. Строка шаблона форматирования представлена в локализованной нотации: десятичный формат определяет, какие именно символы в шаблоне имеют специальное значение (за исключением символа кавычки, который не подлежит локализации). Шаблон формата не должен содержать символ денежной единицы (#x00A4), такая возможность была добавлена уже после первой реализации JDK 1.1. Названием десятичного формата должно быть QName, которое приводится к расширенному имени как описано в главе [2.4 Полные имена]. Если в стиле отсутствует декларация десятичного формата с заданным расширенным именем, фиксируется ошибка.

Замечание: Разработчики не обязаны использовать именно реализацию JDK 1.1, а сам анализатор не обязательно реализовывать на Java.
Замечание: Чтобы контролировать округление чисел, в стилях могут использоваться другие функции из XPath.

<!-- Category: top-level-element -->
<xsl:decimal-format
  name = qname
  decimal-separator = char
  grouping-separator = char
  infinity = string
  minus-sign = char
  NaN = string
  percent = char
  per-mille = char
  zero-digit = char
  digit = char
  pattern-separator = char />

Элемент xsl:decimal-format декларирует десятичный формат, который управляет интерпретацией шаблона формата, используемого в функции format-number. Если присутствует атрибут name, данный элемент декларирует именованный десятичный формат. В остальных случаях декларируется десятичный формат по умолчанию. Значением атрибута name является QName, которое приводится к расширенному имени как было описано в главе [2.4 Полные имена]. Если десятичный формат по умолчанию или десятичный формат с данным именем, декларируется несколько раз, фиксируется ошибка (даже при различном приоритете импорта). Это можно делать только если каждый раз для всех атрибутов декларированы одни и те же значения (принимая во внимание все значения по умолчанию).

Остальные атрибуты xsl:decimal-format соответствуют методам класса DecimalFormatSymbols из JDK 1.1. Для каждой пары методов get/set в элементе xsl:decimal-format определен соответствующий атрибут.

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

  • decimal-separator задает символ, используемый как десятичная точка, по умолчанию используется символ точки (.)

  • grouping-separator задает символ, используемый как разделитель при группировке (например, тысяч), по умолчанию используется символ запятой (,)

  • percent задает символ, используемый как символ процента, по умолчанию используется символ процента (%)

  • per-mille задает символ, используемый как символ промилле, по умолчанию используется символ промилле из набора Unicode (#x2030)

  • zero-digit задает символ, используемый как цифра нуль, по умолчанию используется цифра нуль (0)

Следующие атрибуты задают интерпретацию символов в шаблоне формата:

  • digit задает символ, используемый в шаблоне формата для обозначения цифр, по умолчанию таковым является символ решетки (#)

  • pattern-separator задает символ, используемый для разделения положительной и отрицательной частей в шаблоне, по умолчанию используется символ точки с запятой (;)

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

  • infinity задает строку, используемую для обозначения бесконечности, по умолчанию используется строка Infinity

  • NaN задает строку, используемую для представления значения NaN, по умолчанию используется строка NaN

  • minus-sign задает символ, используемый по умолчанию как знак "минус", по умолчанию используется символ тире-минус (-, #x2D)

12.4 Различные дополнительные функции

Функция: набор-узлов current()

Функция current возвращает набор узлов, состоящий из единственного члена - текущего узла. Для внешнего выражения (выражения, которое не является частью другого выражения), текущий узел всегда тот же самый, что и узел контекста. Таким образом,

<xsl:value-of select="current()"/>

означает то же самое, что и

<xsl:value-of select="."/>

Однако внутри квадратных скобок текущий узел обычно отличается от узла контекста. Например,

<xsl:apply-templates select="//glossary/item[@name=current()/@ref]"/>

будет обрабатывать все элементы item, которые имеют родителем элемент glossary, а также имеют атрибут name, значение которого равно значению атрибута ref текущего узла. Этот вариант отличается от

<xsl:apply-templates select="//glossary/item[@name=./@ref]"/>

который означает то же самое, что

<xsl:apply-templates select="//glossary/item[@name=@ref]"/>

а потому будет обрабатывать все элементы item, которые имеют родителем элемент glossary, а также имеют атрибуты name и ref с одинаковыми значениями.

Если в шаблоне использовать функцию current, фиксируется ошибка.

Функция: строка unparsed-entity-uri(строка)

unparsed-entity-uri возвращает URI неразобранной сущности с заданным именем, находящейся в том же документе, что и узел контекста (см. [3.3 Неразобранные сущности]). Если такой сущности нет, функция возвращает пустую строку.

Функция: строка generate-id(список-узлов?)

Функция generate-id возвращает строку, уникальным образом идентифицирующую тот узел из набора узлов, представленного в аргументе, который первым встретится в документе. Уникальный идентификатор должен состоять из алфавитно-цифровых символов ASCII и должен начинаться с буквы. Таким образом, данная строка синтаксическим соответствует имени XML. Разработчик волен генерировать идентификатор любым удобным ему способом при условии, что для одного и того же узла всегда генерируется один и тот же идентификатор, а для разных узлов всегда генерируются разные идентификаторы. Процессор не обязан генерировать одни и те же идентификаторы при каждом преобразовании документа. Нет гарантий, что сгенерированный уникальный идентификатор не совпадет с каким-либо уникальным ID, указанным у исходном документе. Если в аргументе был дан пустой набор узлов, функция возвращает пустую строку. Если аргумент отсутствует, то по умолчанию используется узел контекста.

Функция: object system-property(строка)

Аргумент функции должен обрабатываться как строка QName. QName приводится к расширенному имени с помощью деклараций пространства имен в области видимости данного выражения. Функция system-property возвращает объект, представляющий значение системного параметра, идентифицируемого этим именем. Если такого системного свойства нет, должна возвращаться пустая строка.

Реализации процессора должны представлять следующие системные свойства, относящиеся к пространству имен XSLT:

  • xsl:version, число, указывающее версию XSLT, реализуемую данным процессором. Для XSLT процессоров, реализующих версию XSLT, описываемую данным документом, таким числом является 1.0
  • xsl:vendor, строка, идентифицирующая разработчика XSLT процессора
  • xsl:vendor-url, строка, содержащая URL, идентифицирующий разработчика данного XSLT процессора. Как правило, это страница хоста (домашняя страница) Web-сайта разработчика.

13 Сообщения

<!-- Category: instruction -->
<xsl:message
  terminate = "yes" | "no">
  <!-- Content: template -->
</xsl:message>

Инструкция xsl:message посылает сообщение, причем способ отправки зависит от XSLT процессора. Содержимое инструкции xsl:message является шаблоном. xsl:message обрабатывается путем подстановки его содержимого в создаваемый XML фрагмент. Этот XML фрагмент является содержимым посылаемого сообщения.

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

Если атрибут terminate имеет значение yes, то после посылки сообщения XSLT процессор должен завершить обработку. Значением по умолчанию является no.

Одним из удобных способов локализации состоит в том, чтобы поместить локализованную информацию (текст сообщения и прочего) в некий XML документ, который станет для стиля дополнительным входным файлом. Предположим к примеру что сообщение для языка L помещено в XML-файл resources/L.xml в следующем формате:

<messages>
  <message name="problem">A problem was detected.</message>
  <message name="error">An error was detected.</message>
</messages>

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

<xsl:param name="lang" select="en"/>
<xsl:variable name="messages"

  select="document(concat('resources/', $lang, '.xml'))/messages"/>

<xsl:template name="localized-message">

  <xsl:param name="name"/>
  <xsl:message>
    <xsl:value-of select="$messages/message[@name=$name]"/>
  </xsl:message>
</xsl:template>

<xsl:template name="problem">
  <xsl:call-template name="localized-message"/>
    <xsl:with-param name="name">problem</xsl:with-param>
  </xsl:call-template>
</xsl:template>

14 Расширения

XSLT допускает два типа расширений: элементы расширения и функции расширения.

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

14.1 Элементы расширения

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

Замечание: Поскольку элемент, являющийся непосредственным потомком элемента xsl:stylesheet, в шаблон не попадает, то не-XSLT элементы верхнего уровня не относятся к описываемым здесь элементам расширения, не применяется к ним и ни одно из указаний, данных в этой главе.

Пространство имен объявляется пространством имен расширения с помощью атрибута extension-element-prefixes в элементе xsl:stylesheet, либо атрибута xsl:extension-element-prefixes в фиксированном конечном элементе или элементе расширения. Значением обоих этих атрибутов является перечень (через пробельный символ) префиксов пространства имен. Пространство имен, связанное с каждым из представленных префиксов, рассматривается как пространство имен расширения. Если пространство имен, привязанное к префиксу в элементе, имеющем атрибут extension-element-prefixes или xsl:extension-element-prefixes, отсутствует, фиксируется ошибка. Пространство имен по умолчанию (декларируемое с помощью xmlns) также может быть объявлено как пространство имен расширений если в описываемый перечень префиксов пространства имен включить #default. Объявление пространства имен в качестве пространства имен расширений действительно в стиле в пределах поддерева, начинающегося с того элемента, которому принадлежит атрибут extension-element-prefixes или xsl:extension-element-prefixes. Поддерево, начинающееся с элемента xsl:stylesheet, не включает каких-либо стилей, импортированных или включенных непосредственными потомками этого элемента xsl:stylesheet.

Если XSLT процессору недоступна реализация определенного элемента расширения, функция element-available в ответ на имя этого элемента должна возвращать false. Когда подобный элемент расширения обрабатывается, XSLT процессор должен выполнить для этого элемента откат, как описано в главе [15 Откат]. При этом XSLT процессор не должен фиксировать ошибку только потому, что шаблон содержит элемент расширения, реализация которого оказалась недоступна.

Если XSLT процессору доступна реализация конкретного элемента расширения, то в ответ на имя этого элемента функция element-available должна возвращать true.

14.2 Функции расширения

Если FunctionName в выражении FunctionCall не является NCName (например, содержит двоеточие), то оно обрабатывается как вызов функции расширения. FunctionName приводится к расширенному имени с помощью деклараций пространства имен, извлеченных из контекста обработки.

Если XSLT процессору недоступна реализация функции расширения с указанным именем, то тогда функция function-available в ответ на это имя должна возвращать false. Если в выражении была найдена такая функция расширения и действительно был сделан вызов этой функции расширения, то XSLT процессор должен фиксировать ошибку. Однако XSLT процессор не должен сигнализировать об ошибке только потому, что некое выражение содержит функцию расширения, для которой нет доступной реализации.

Если реализация функции расширения с указанным именем доступна XSLT процессору, функция function-available для этого имени должна возвращать true. Если сделан вызов такого расширения, XSLT процессор должен вызвать данную реализацию, передав ей аргументы вызова этой функции. Результат, полученный от вызова реализации, передается как результат вызова функции.

15 Откат

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

Обычно обработка элемента xsl:fallback ничего не меняет. Однако когда XSLT процессор осуществляет откат для элемента инструкции, а этот элемент инструкции имеет один или несколько непосредственных потомков xsl:fallback, должно быть последовательно обработано содержимое каждого из этих потомков xsl:fallback. В противном случае должна фиксироваться ошибка. Содержимое элемента xsl:fallback является шаблоном.

Приведенные далее функции могут быть использованы с инструкциями xsl:choose и xsl:if чтобы явно задавать поведение стиля в случае, если определенные стили или функции будут недоступны.

Функция: boolean element-available(строка)

Аргумент функции должен обрабатываться как строка, соответствующая QName. QName преобразуется в расширенное имя с помощью деклараций пространства имен из области видимости данного выражения. Функция element-available возвращает true тогда и только тогда, когда это расширенное имя является названием инструкции. Если URI пространства имен в расширенном имени равно URI пространства имен XSLT, то это имя относится к элементу, объявленному в XSLT. В противном случае расширенное имя относится к элементу расширения. Если расширенное имя имеет нулевой URI пространства имен, функция element-available будет возвращать false.

Функция: boolean function-available(строка)

Аргумент функции должен обрабатываться как строка, соответствующая QName. QName приводится к расширенному имени с помощью деклараций пространства имен в области видимости данного выражения. Функция function-available возвращает true тогда и только тогда, когда расширенное имя является названием некой функции из библиотеки функций. Если расширенное имя имеет ненулевой URI пространства имен, то оно относится к функции расширения. В противном случае имя относится к функции, определенной в XPath или XSLT.

16 Вывод

<!-- Category: top-level-element -->
<xsl:output
  method = "xml" | "html" | "text" | qname-but-not-ncname
  version = nmtoken
  encoding = string
  omit-xml-declaration = "yes" | "no"
  standalone = "yes" | "no"
  doctype-public = string
  doctype-system = string
  cdata-section-elements = qnames
  indent = "yes" | "no"
  media-type = string />

XSLT процессор может выводить конечное дерево в виде последовательности байтов, хотя и не обязан иметь такую возможность (см. [17 Соответствие спецификации]). Элемент xsl:output позволяет авторам стилей указывать, каким они хотят видеть конечное дерево при выводе. Если XSLT процессор выводит на печать конечное дерево, он должен делать это так, как задано элементом xsl:output, однако сам вывод процессор выполнять не обязан.

Элемент xsl:output можно использовать только как элемент верхнего уровня.

Атрибут method в xsl:output идентифицирует общий метод, который должен использоваться для вывода конечного дерева. Значением атрибута должно быть QName. Если QName не имеет префикса, то оно идентифицирует метод, описываемый данным документом, и должно соответствовать одному из трех названий: xml, html или text. Если QName имеет префикс, то такое QName приводится к расширенному имени, как описано в главе [2.4 Полные имена]. Расширенное имя идентифицирует метод вывода. Поведение в этом случае данный документ не описывает.

По умолчанию атрибут method выбирается следующим образом. Если

  • корневой узел конечного дерева имеет элемент непосредственным потомком,

  • расширенное имя первого элемента в конечном дереве, который является непосредственным потомком корневого узла (например, элемент документа) имеет локальную часть html (в любом сочетании верхних и нижних регистров) и нулевой URI пространства имен,

  • все текстовые узлы, предшествующие первому элементу в конечном дереве, являющемуся непосредственным потомком корневого узла, содержат только пробельные символы,

то тогда методом вывода по умолчанию является html. В противном случае таковым является xml. Метод вывода по умолчанию должен быть использован если нет элементов xsl:output, либо ни один элемент xsl:output не определяет значения атрибута method.

Остальные атрибуты в xsl:output определяют параметры для метода вывода. Разрешается использовать следующие атрибуты:

  • version указывает версию метода вывода

  • indent указывает, может ли XSLT процессор ставить дополнительные пробелы при выводе конечного дерева, атрибут должен иметь значение yes или no

  • encoding указывает предпочтительную кодировку символов, которую XSLT процессор должен использовать чтобы представить последовательность символов в виде последовательности байтов. Значение атрибута должно обрабатываться независимо от используемого регистра. Значение атрибута должно состоять из символов из диапазона от #x21 до #x7E (т.е. печатных ASCII символов). Значением должно быть либо charset, зарегистрированный Internet Assigned Numbers Authority [IANA], [RFC2278], либо строка начинающаяся с X-

  • media-type определяет тип среды (тип контента MIME) для данных, полученных при выводе конечного дерева. Параметр charset не должен указываться явно. Наоборот, параметр charset должен добавляется когда типом среды на верхнем уровне является text, причем в соответствии с той кодировкой символов, которая реально используется данным методом вывода

  • doctype-system указывает системный идентификатор, который должен использоваться в декларации типа документа

  • doctype-public указывает публичный идентификатор, который должен использоваться в декларации типа документа

  • omit-xml-declaration указывает, должен ли XSLT процессор выводить декларацию XML, значением атрибута должно быть yes или no

  • standalone указывает, должен ли XSLT процессор выводить декларацию одиночного документа. Значением атрибута должно быть yes или no

  • cdata-section-elements определяет перечень названий элементов, чьи непосредственные потомки, являющиеся текстовыми узлами, должны печататься с помощью блоков CDATA

Детальная семантика каждого атрибута будет описана отдельно для каждого метода вывода, в котором он используется. Если семантика атрибута для метода вывода не описана, использовать ее для этого метода нельзя.

Стиль может содержать несколько элементов xsl:output, а также может включить или импортировать другие стили, также содержащие элементы xsl:output. Все элементы xsl:output, обнаруженные в стиле, объединяются в один эффективный элемент xsl:output. Для атрибута cdata-section-elements эффективное значение является объединением всех указанных значений. Для остальных атрибутов эффективным является значение, указанное с наивысшим приоритетом импорта. Если таких значений для атрибута было несколько, фиксируется ошибка. XSLT процессор может фиксировать такую ошибку. Если он этого не делает, то должен обрабатывать ошибку сам, используя то значение, которое в стиле было обнаружено последним. Значения атрибутов берутся по умолчанию после того, как были объединены элементы xsl:output, разные методы вывода по умолчанию могут иметь различные значения атрибута.

16.1 Метод вывода XML

Метод вывода xml выводит конечное дерево как корректную внешнюю общую разобранную сущность XML. Если корневой узел конечного дерева имеет непосредственным потомком только один узел элемента и не имеет непосредственными потомками текстовые узлы, то эта сущность также должна быть корректной сущностью документа XML. Если на сущность ссылается простой упаковщик XML документа, такой как

<!DOCTYPE doc [
<!ENTITY e SYSTEM "entity-URI">
]>
<doc>&e;</doc>

где entity-URI - URI данной сущности, то документ упаковщика в целом должен быть корректным XML документом, отвечающим требованиям Рекомендации для Пространства имен XML [XML Names]. Кроме того, вывод должен быть таким, чтобы если путем разбора этого упаковщика как XML документа построить новое дерево как было описано в главе [3 Модель данных], а затем изъять элемент документа и поставить его непосредственного потомка вместо непосредственного потомка корневого узла, то новое дерево будет таким же как конечное дерево за следующими возможными исключениями:

  • В двух деревьях может отличаться порядок следования атрибутов.

  • Новое дерево может содержать узлы пространства имен, которые не были представлены в конечном дереве.

    Замечание: В ходе вывода конечного дерева как XML XSLT процессору может потребоваться добавить декларации пространства имен.

Если XSLT процессор генерирует декларацию типа документа на основании атрибута doctype-system, то приведенные выше требования относятся и к сущности, в которой изъята сгенерированная декларация типа документа.

Атрибут version указывает версию XML, которая должна использоваться для вывода конечного дерева. Если XSLT процессор не поддерживает указанную версию XML, должна использоваться та версия XML, которую он поддерживает. Версия вывода в декларации XML (если декларация XML выводится) должна соответствовать той версии XML, которую процессор использует для вывода конечного дерева. Значение атрибута version должно соответствовать сценарию VersionNum из Рекомендации XML [XML]. Значение по умолчанию - 1.0.

Атрибут encoding указывает предпочтительную кодировку, которая должна использоваться при выводе конечного дерева. XSLT процессоры должны поддерживать значения UTF-8 и UTF-16. Для других значений, если XSLT процессор не поддерживает соответствующую кодировку, он должен фиксировать ошибку. Если же он этого не делает, то вместо указанной кодировки должен использовать UTF-8 или UTF-16. XSLT процессор не должен пользоваться кодировкой, название которой не соответствует сценарию EncName из Рекомендации XML [XML]. Если атрибут encoding не указан, XSLT процессор должен использовать UTF-8 или UTF-16. Есть вероятность, что в конечном дереве обнаружится символ, который нельзя представить в кодировке, которую XSLT процессор использует для вывода. В таком случае, если данный символ был обнаружен в контексте, где XML распознает ссылки на символы (то есть, в значении узла атрибута или узла текста), то этот символ следует представить в виде ссылки на символ. В противном случае (например, если символ был обнаружен в названии элемента) XSLT процессор должен фиксировать ошибку.

Если атрибут indent имеет значение yes, то метод вывода xml в дополнение к пробельным символам в конечном дереве может показывать собственные пробельные символы (возможно потому, что пробельные символы будут удалены из исходного документа или из стиля) с тем, чтобы получить более красивый результат. Если атрибут indent имеет значение no, какие-либо дополнительные пробельные символы появляться не должны. Значением атрибута по умолчанию является no. Для размещения дополнительных пробельных символов метод вывода xml должен использовать такой алгоритм, который гарантирует, что когда пробельные символы изъяты из вывода с помощью процедуры, описанной в главе [3.4 Удаление пробельных символов], а список элементов, сохраняющих пробельные символы, ограничивается лишь xsl:text, результат будет таким же, как если дополнительные пробельные символы не использовались.

Замечание: Для тех типов документов, которые содержат элементы со смешанным содержимым, использовать indent="yes" обычно небезопасно.

Атрибут cdata-section-elements содержит список QName (разделенных пробельными символами). Каждый QName приводится к расширенному имени с помощью деклараций пространства имен, в области действия которых находится элемент xsl:output с данным QName. Если имеется пространство имен по умолчанию, то оно используется для тех QName, которые своего префикса не имеют. Расширение выполняется до того, как несколько элементов xsl:output будут объединены в один эффективный элемент xsl:output. Если членом данного переченя является расширенное имя родителя текстового узла, то сам текстовый узел должен быть представлен в виде блока CDATA. Например,

<xsl:output cdata-section-elements="example"/>

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

<example>&lt;foo></example>

или

<example><![CDATA[<foo>]]></example>

будет представлен как

<example><![CDATA[<foo>]]></example>

Если текстовый узел содержит последовательность символов ]]>, то текущий открытый блок CDATA будет закрыт сразу после ]], а перед > будет открыт новый блок CDATA. Например, фиксированный конечный элемент, записанный в стиле как

<example>]]&gt;</example>

будет представлен в виде

<example><![CDATA[]]]]><![CDATA[>]]></example>

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

Блоки CDATA не должны использоваться за исключением тех текстовых узлов, где атрибут cdata-section-elements явно требует вывода с помощью блоков CDATA.

Метод вывода xml должен предоставить декларацию XML, если атрибут omit-xml-declaration не имеет значения yes. Декларация XML должна содержать и информацию о версии, и декларацию кодировки. Если указан атрибут standalone, то должна быть включена декларация одиночного документа с тем же значением, какое было у атрибута standalone. В противном случае декларация одиночного документа быть не должно. Тем самым гарантируется, что будут присутствовать и декларация XML (допустимая в начале сущности документа) и декларация текста (допустимая в начале внешней общей разобранной сущности).

Если указан атрибут doctype-system, метод вывода xml должен ставить декларацию типа документа непосредственно перед первым элементом. Имя, следующее за <!DOCTYPE, должно быть названием этого первого элемента. Если к тому же указан атрибут doctype-public, то метод вывода xml за PUBLIC должен сперва поставить публичный идентификатор, а затем системный идентификатор. В противном случае, за SYSTEM должен следовать системный идентификатор. Внутренний набор декларации должен быть пуст. Если атрибут doctype-system не указан, атрибут doctype-public следует игнорировать.

Для метода вывода xml можно использовать атрибут media-type. Значением по умолчанию для атрибута media-type является text/xml.

16.2 Метод вывода HTML

Метод вывода html представляет конечное дерево в виде HTML. Например,

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

<xsl:output method="html"/>
 <xsl:template match="/">
  <html>
   <xsl:apply-templates/>
  </html>
</xsl:template>

...

</xsl:stylesheet>

Атрибут version показывает версию HTML. Значением по умолчанию является 4.0, означающее, что результат должен быть выведен как HTML документ, отвечающий Рекомендации HTML 4.0 [HTML].

Метод вывода html не должен представлять элемент, иначе чем метод xml, если расширенное имя этого элемента имеет ненулевой URI пространства имен. Элемент, чье расширенное имя имеет ненулевой URI пространства имен, должен быть представлен как XML. Если расширенное имя элемента имеет нулевой URI пространства имен, но локальная часть этого имени как название элемента HTML не распознается, этот элемент должен быть представлен как непустой встроенный элемент, такой как span.

Метод вывода html для пустых элементов не должен показывать конечный тэг. В HTML 4.0 пустыми элементами являются area, base, basefont, br, col, frame, hr, img, input, isindex, link, meta и param. Например, элемент, указанный в стиле как <br/> или <br></br>, должен быть представлен как <br>.

Метод вывода html должен распознавать названия HTML элементов независимо от регистра. Например, все элементы с названиями br, BR и Br должны распознаваться как HTML элемент br и показываться без закрывающего тэга.

Метод вывода html не должен выполнять маскирование содержимого элементов script и style. Например, фиксированный конечный элемент, записанный в стиле как

<script>if (a &lt; b) foo()</script>

или

<script><![CDATA[if (a < b) foo()]]></script>

должен быть представлен как

<script>if (a < b) foo()</script>

Метод вывода html не должен маскировать символы <, встретившиеся в значении атрибутов.

Если атрибут indent имеет значение yes, то метод вывода html, показывая конечное дерево, может добавлять или, наоборот, удалять пробельные символы ровно до тех пор, пока это не влияет на то, как HTML-агент пользователя будет отображать результат вывода. По умолчанию атрибут имеет значение yes.

В значении атрибутов URI метод вывода html должен маскировать символы, не относящиеся к набору ASCII, используя метод, рекомендованный в главе B.2.1 Рекомендации HTML 4.0.

Метод вывода html может показать любой символ, воспользовавшись ссылкой на сущность символа, если таковая определена в той версии HTML, которую использует данный метод вывода.

Инструкции обработки метод вывода html должен завершать символом >, а не комбинацией ?>.

Булевы атрибуты (то есть, такие атрибуты, которым разрешено иметь только одно значение - название самого атрибута) метод вывода html должен показывать в минимизированной форме. Например, начальный тэг, записанный в стиле как

<OPTION selected="selected">

должен быть представлен в виде

<OPTION selected>

В значении атрибута метод вывода html не должен маскировать символ &, сразу за которым следует символ { (см. главу B.7.1 в Рекомендации HTML 4.0). Например, начальный тэг, записанный в стиле как

<BODY bgcolor='&amp;{{randomrbg}};'>

должен быть представлен в виде

<BODY bgcolor='&{randomrbg};'>

Атрибут encoding указывает, какая должна использоваться предпочтительная кодировка. Если имеется элемент HEAD, то метод вывода html сразу после начального элемента HEAD должен добавить элемент META, указывающий реально используемую кодировку символов. Например,

<HEAD>
<META http-equiv="Content-Type" content="text/html; charset=EUC-JP">
...

Может оказаться, что конечное дерево содержит символ, который невозможно представить в той кодировке, которую XSLT процессор использует для вывода. В этом случае, если символ встретился в таком контексте, где HTML распознает ссылки на символы, то этот символ должен быть представлен ссылкой на сущность символа или десятичной числовой ссылкой на символ. В противном случае (например, в элементе script, style или в комментарии), XSLT процессор должен фиксировать ошибку.

Если указаны атрибуты doctype-public или doctype-system, метод вывода html непосредственно перед первым элементом должен представить декларацию типа документа. Именем, следующим за <!DOCTYPE, должно быть HTML или html. Если указан атрибут doctype-public, метод вывода должен представить PUBLIC, за которым следует указанный публичный идентификатор. Если дополнительно указан атрибут doctype-system, то перед публичным идентификатором должен быть показан указанный системный идентификатор. Если указан атрибут doctype-system, но не было атрибута doctype-public, метод вывода должен представить SYSTEM, за которым следует указанный системный идентификатор.

Для метода вывода html можно использовать атрибут media-type. По умолчанию подразумевается значение text/html.

16.3 Метод вывода Text

Метод вывода text представляет конечное дерево, показывая строковое значение каждого текстового узла в конечном дереве, причем в том порядке, как они следуют в документе, и без какого-либо маскирования.

Для метода вывода text можно использовать атрибут media-type. Значением по умолчанию для атрибута media-type является text/plain.

Атрибут encoding указывает кодировку, которую метод вывода text должен использовать для преобразования последовательностей символов в последовательности байтов. Значение по умолчанию для этого атрибута зависит от системы. Если в конечном дереве есть символ, который невозможно представить в той кодировке, которую XSLT процессор использует для вывода, XSLT процессор должен фиксировать ошибку.

16.4 Запрет маскирования при выводе

Обычно метод вывода xml, представляя текстовые узлы, маскирует & и < (а также, возможно, и другие символы). Тем самым обеспечивается вывод корректного XML документа. Иногда однако бывает удобно иметь возможность показывать почти, но не совсем корректный документ XML. Например, вывод может содержать некорректные разделы, которые будут преобразованы в корректный XML последующей процедурой, не связанной с XML. По этой причине XSLT предоставляет механизм запрета маскирования при выводе. Элементы xsl:value-of или xsl:text могут содержать атрибут disable-output-escaping, который может иметь значения yes или no. По умолчанию подразумевается значение no. Если значение атрибута yes, текстовый узел, полученный обработкой элемента xsl:value-of или xsl:text, должен быть представлен без маскирования. Например,

<xsl:text disable-output-escaping="yes">&lt;</xsl:text>

должен сгенерировать единственный символ <.

Если маскирование при выводе было запрещено для текстового узла, который используется где-либо еще кроме текстового узла в конечном дереве, фиксируется ошибка. Таким образом, будет ошибкой запретить маскирование для элемента xsl:value-of или xsl:text, который используется для получения строкового значения к комментарию, инструкции обработки или узлу атрибута. Ошибкой будет также преобразование фрагмента конечного дерева в число или строку, если в этом фрагменте содержится текстовый узел, для которого было запрещено маскирование. В обоих случаях XSLT процессор может фиксировать ошибку. Если он этого не делает, то должен обработать ошибку сам, игнорируя атрибут disable-output-escaping.

Атрибут disable-output-escaping можно использовать и для метода вывода html, и для метода вывода xml. Метод вывода text игнорирует атрибут disable-output-escaping, поскольку при выводе не делает какого-либо маскирования.

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

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

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

17 Соответствие спецификации

XSLT процессор, соответствующий спецификации, должен уметь использовать стиль для преобразования исходного дерева в конечное дерево так, как было описано в данном документе. Соответствующий спецификации XSLT процессор не обязан уметь представить результат в виде XML или в каком-либо ином формате.

Замечание: Разработчикам XSLT процессоров настоятельно рекомендуется обеспечить возможность проверить, что их процессор работает согласно требованиям спецификации. Для этого необходимо разрешить вывод конечного дерева в виде XML или предоставить доступ к конечному дереву через стандартный API, такой как DOM или SAX.

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

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

18 Нотация

Спецификации каждого определенного в XSLT типа элементов предшествует описание его синтаксиса в форме модели для элементов указанного типа. Нотация к описанию синтаксиса имеет следующее значение:

  • Атрибут является обязательным тогда и только тогда, когда его название выделено жирным шрифтом.

  • Строка, которая указана вместо значения атрибута, указывает допустимые значения атрибута. Если строка окружена фигурными скобками, значение атрибута обрабатывается как шаблон значения атрибута, строка же, находящаяся в фигурных скобках, указывает допустимые значения, которые можеь иметь результат обработки шаблона значения атрибута. Альтернативные значения отделены друг от друга символом |. Строка, заключенная в кавычки, дает значение, соответствующее этой строке. Имя, не заключенное в кавычки и набранное наклонным шрифтом, задает определенный тип значения.

  • Если элемент может быть не пустым, то этот элемент содержит комментарий, описывающий разрешенное содержимое. Разрешенное содержимое задается точно так же, как декларация типа элемента в XML. Запись template означает, что можно использовать любое сочетание текстовых узлов, фиксированных конечных элементов, элементов расширения и XSLT элементов из категории instruction. Запись top-level-elements означает, что можно использовать любое сочетание XSLT элементов из категории top-level-element.

  • Элементу предшествуют комментарии, указывающие, принадлежит ли он категории instruction, категории top-level-element или обеим. Категория элемента влияниет лишь на то, можно ли его использовать в содержимом элементов, допускающих template или top-level-elements.

A Ссылки

A.1 Нормативные ссылки

XML
World Wide Web Consortium. Extensible Markup Language (XML) 1.0. Рекомендации W3C. См. http://www.w3.org/TR/1998/REC-xml-19980210
Names XML
World Wide Web Consortium. Namespaces in XML. Рекомендации W3C. См. http://www.w3.org/TR/REC-xml-names
XPath
World Wide Web Consortium. XML Path Language. Рекомендации W3C. См. http://www.w3.org/TR/xpath

A.2 Остальные ссылки

CSS2
World Wide Web Consortium. Cascading Style Sheets, level 2 (CSS2). Рекомендации W3C. См. http://www.w3.org/TR/1998/REC-CSS2-19980512
DSSSL
Международная организация по стандартизации, Международная электротехническая комиссия. ISO/IEC 10179:1996. Document Style Semantics and Specification Language (DSSSL). Международный стандарт.
HTML
World Wide Web Consortium. HTML 4.0 specification. Рекомендации W3C. См. http://www.w3.org/TR/REC-html40
IANA
Internet Assigned Numbers Authority. Character Sets. См. ftp://ftp.isi.edu/in-notes/iana/assignments/character-sets.
RFC2278
N. Freed, J. Postel. IANA Charset Registration Procedures. IETF RFC 2278. См. http://www.ietf.org/rfc/rfc2278.txt.
RFC2376
E. Whitehead, M. Murata. XML Media Types. IETF RFC 2376. См. http://www.ietf.org/rfc/rfc2376.txt.
RFC2396
T. Berners-Lee, R. Fielding, and L. Masinter. Uniform Resource Identifiers (URI): Generic Syntax. IETF RFC 2396. См. http://www.ietf.org/rfc/rfc2396.txt.
UNICODE TR10
Unicode Consortium. Unicode Technical Report #10. Unicode Collation Algorithm. Unicode Technical Report. См. http://www.unicode.org/unicode/reports/tr10/index.html.
XHTML
World Wide Web Consortium. XHTML 1.0: The Extensible HyperText Markup Language. Предложенная рекомендация W3C. См. http://www.w3.org/TR/xhtml1
XPointer
World Wide Web Consortium. XML Pointer Language (XPointer). Предварительный рабочий документ W3C. См. http://www.w3.org/TR/xptr
XML Stylesheet
World Wide Web Consortium. Associating stylesheets with XML documents. Рекомендация W3C. См. http://www.w3.org/TR/xml-stylesheet
XSL
World Wide Web Consortium. Extensible Stylesheet Language (XSL). Предварительный рабочий документ W3C. См. http://www.w3.org/TR/WD-xsl

B Справочник синтаксиса элементов

<!-- Category: instruction -->
<xsl:apply-imports />

<!-- Category: instruction -->
<xsl:apply-templates
  select = node-set-expression
  mode = qname>
  <!-- Content: (xsl:sort | xsl:with-param)* -->
</xsl:apply-templates>

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

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

<!-- Category: instruction -->
<xsl:call-template
  name = qname>
  <!-- Content: xsl:with-param* -->
</xsl:call-template>

<!-- Category: instruction -->
<xsl:choose>
  <!-- Content: (xsl:when+, xsl:otherwise?) -->
</xsl:choose>

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

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

<!-- Category: instruction -->
<xsl:copy-of
  select = expression />

<!-- Category: top-level-element -->
<xsl:decimal-format
  name = qname
  decimal-separator = char
  grouping-separator = char
  infinity = string
  minus-sign = char
  NaN = string
  percent = char
  per-mille = char
  zero-digit = char
  digit = char
  pattern-separator = char />

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

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

<!-- Category: instruction -->
<xsl:for-each
  select = node-set-expression>
  <!-- Content: (xsl:sort*, template) -->
</xsl:for-each>

<!-- Category: instruction -->
<xsl:if
  test = boolean-expression>
  <!-- Content: template -->
</xsl:if>

<xsl:import
  href = uri-reference />

<!-- Category: top-level-element -->
<xsl:include
  href = uri-reference />

<!-- Category: top-level-element -->
<xsl:key
  name = qname
  match = pattern
  use = expression />

<!-- Category: instruction -->
<xsl:message
  terminate = "yes" | "no">
  <!-- Content: template -->
</xsl:message>

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

<!-- 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:otherwise>
  <!-- Content: template -->
</xsl:otherwise>

<!-- Category: top-level-element -->
<xsl:output
  method = "xml" | "html" | "text" | qname-but-not-ncname
  version = nmtoken
  encoding = string
  omit-xml-declaration = "yes" | "no"
  standalone = "yes" | "no"
  doctype-public = string
  doctype-system = string
  cdata-section-elements = qnames
  indent = "yes" | "no"
  media-type = string />

<!-- Category: top-level-element -->
<xsl:param
  name = qname
  select = expression>
  <!-- Content: template -->
</xsl:param>

<!-- Category: top-level-element -->
<xsl:preserve-space
  elements = tokens />

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

<xsl:sort
  select = string-expression
  lang = { nmtoken }
  data-type = { "text" | "number" | qname-but-not-ncname }
  order = { "ascending" | "descending" }
  case-order = { "upper-first" | "lower-first" } />

<!-- Category: top-level-element -->
<xsl:strip-space
  elements = tokens />

<xsl:stylesheet
  id = id
  extension-element-prefixes = tokens
  exclude-result-prefixes = tokens
  version = number>
  <!-- Content: (xsl:import*, top-level-elements) -->
</xsl:stylesheet>

<!-- Category: top-level-element -->
<xsl:template
  match = pattern
  name = qname
  priority = number
  mode = qname>
  <!-- Content: (xsl:param*, template) -->
</xsl:template>

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

<xsl:transform
  id = id
  extension-element-prefixes = tokens
  exclude-result-prefixes = tokens
  version = number>
  <!-- Content: (xsl:import*, top-level-elements) -->
</xsl:transform>

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

<!-- Category: top-level-element -->
<!-- Category: instruction -->
<xsl:variable
  name = qname
  select = expression>
  <!-- Content: template -->
</xsl:variable>

<xsl:when
  test = boolean-expression>
  <!-- Content: template -->
</xsl:when>

<xsl:with-param
  name = qname
  select = expression>
  <!-- Content: template -->
</xsl:with-param>

C Фрагмент DTD для стилей XSLT (пояснения к спецификации)

Замечание: Данный фрагмент DTD не является нормативным, поскольку в XML 1.0 DTD не поддерживают пространства имен XML, а потому не могут корректно описывать структуру, допустимую для стиля XSLT.

Приводимая далее сущность может использоваться при создании DTD для XSLT стилей, который создает экземпляры уже конкретного конечного DTD. Прежде чем ссылаться на сущность, стиль DTD должен определить сущность параметра result-elements, дающего перечень разрешенных типов данного конечного элемента. Например,

<!ENTITY % result-elements "
  | fo:inline-sequence
  | fo:block
">

Должно быть декларировано, что такие конечное элементы имеют атрибуты xsl:use-attribute-sets и xsl:extension-element-prefixes. Для этой цели приводимая далее сущность декларирует параметр result-element-atts. XSLT позволяет конечным элементам иметь то же самое содержимое, которое допускалось для элементов XSLT, декларированных в следующей сущности с моделью содержимого %template;. DTD может использовать более ограничивающую модель содержимого, чем %template; чтобы отразить ограничения в конечном DTD.

DTD может определить сущность параметра non-xsl-top-level с тем, чтобы разрешить использование дополнительных элементов верхнего уровня из других пространств имен, помимо пространства имен XSLT.

Использование префикса xsl: в этом DTD не означает, что стили XSLT обязаны использовать этот префикс. Любой из элементов, декларированных в этом DTD, в дополнение к атрибутам, декларированным в этом же DTD, может иметь атрибуты, имена которых начинаются с xmlns: или равны xmlns.

<!ENTITY % char-instructions "
  | xsl:apply-templates
  | xsl:call-template
  | xsl:apply-imports
  | xsl:for-each
  | xsl:value-of
  | xsl:copy-of
  | xsl:number
  | xsl:choose
  | xsl:if
  | xsl:text
  | xsl:copy
  | xsl:variable
  | xsl:message
  | xsl:fallback
">

<!ENTITY % instructions "
  %char-instructions;
  | xsl:processing-instruction
  | xsl:comment   | xsl:element   | xsl:attribute
">

<!ENTITY % char-template "
 (#PCDATA
  %char-instructions;)*
">

<!ENTITY % template "
  (#PCDATA
  %instructions;
  %result-elements;)*
">

<!-- Used for the type of an attribute value that is a URI reference.-->
<!ENTITY % URI "CDATA">

<!-- Used for the type of an attribute value that is a pattern.-->
<!ENTITY % pattern "CDATA">

<!-- Used for the type of an attribute value that is an
     attribute value template.-->
<!ENTITY % avt "CDATA">

<!-- Used for the type of an attribute value that is a QName; the prefix
     gets expanded by the XSLT processor. -->
<!ENTITY % qname "NMTOKEN">

<!-- Like qname but a whitespace-separated list of QNames. -->
<!ENTITY % qnames "NMTOKENS">

<!-- Used for the type of an attribute value that is an expression.-->
<!ENTITY % expr "CDATA">

<!-- Used for the type of an attribute value that consists      of a single character.-->
<!ENTITY % char "CDATA">

<!-- Used for the type of an attribute value that is a priority. --> <!ENTITY % priority "NMTOKEN">
<!ENTITY % space-att "xml:space (default|preserve) #IMPLIED">

<!-- This may be overridden to customize the set of elements allowed
at the top-level. -->
 <!ENTITY % non-xsl-top-level "">

<!ENTITY % top-level "
 (xsl:import*,
  (xsl:include
  | xsl:strip-space
  | xsl:preserve-space
  | xsl:output
  | xsl:key
  | xsl:decimal-format
  | xsl:attribute-set
  | xsl:variable
  | xsl:param
  | xsl:template
  | xsl:namespace-alias
  %non-xsl-top-level;)*)
">
<!ENTITY % top-level-atts '   extension-element-prefixes CDATA #IMPLIED
  exclude-result-prefixes CDATA #IMPLIED
  id ID #IMPLIED
  version NMTOKEN #REQUIRED   xmlns:xsl CDATA #FIXED "http://www.w3.org/1999/XSL/Transform"
  %space-att;
'>

<!-- This entity is defined for use in the ATTLIST declaration for result elements. -->
<!ENTITY % result-element-atts '
  xsl:extension-element-prefixes CDATA #IMPLIED
  xsl:exclude-result-prefixes CDATA #IMPLIED
  xsl:use-attribute-sets %qnames; #IMPLIED
  xsl:version NMTOKEN #IMPLIED
'>

<!ELEMENT xsl:stylesheet %top-level;>
<!ATTLIST xsl:stylesheet %top-level-atts;>

<!ELEMENT xsl:transform %top-level;>
<!ATTLIST xsl:transform %top-level-atts;>

<!ELEMENT xsl:import EMPTY>
<!ATTLIST xsl:import href %URI; #REQUIRED>

<!ELEMENT xsl:include EMPTY>
<!ATTLIST xsl:include href %URI; #REQUIRED>

<!ELEMENT xsl:strip-space EMPTY>
<!ATTLIST xsl:strip-space elements CDATA #REQUIRED>

<!ELEMENT xsl:preserve-space EMPTY>
<!ATTLIST xsl:preserve-space elements CDATA #REQUIRED>

<!ELEMENT xsl:output EMPTY>
<!ATTLIST xsl:output
  method %qname; #IMPLIED
  version NMTOKEN #IMPLIED   encoding CDATA #IMPLIED
  omit-xml-declaration (yes|no) #IMPLIED
  standalone (yes|no) #IMPLIED
  doctype-public CDATA #IMPLIED
  doctype-system CDATA #IMPLIED
  cdata-section-elements %qnames; #IMPLIED
  indent (yes|no) #IMPLIED   media-type CDATA #IMPLIED
>

<!ELEMENT xsl:key EMPTY>
<!ATTLIST xsl:key
  name %qname; #REQUIRED
  match %pattern; #REQUIRED   use %expr; #REQUIRED
>

<!ELEMENT xsl:decimal-format EMPTY>
<!ATTLIST xsl:decimal-format
  name %qname; #IMPLIED
  decimal-separator %char; "."
  grouping-separator %char; ","
  infinity CDATA "Infinity"   minus-sign %char; "-"   NaN CDATA "NaN"
  percent %char; "%"   per-mille %char; "&#x2030;"
  zero-digit %char; "0"
  digit %char; "#"
  pattern-separator %char; ";"
 >

<!ELEMENT xsl:namespace-alias EMPTY>
<!ATTLIST xsl:namespace-alias
  stylesheet-prefix CDATA #REQUIRED
  result-prefix CDATA #REQUIRED
>

<!ELEMENT xsl:template
 (#PCDATA
  %instructions;
  %result-elements;
  | xsl:param)* >
<!ATTLIST xsl:template
  match %pattern; #IMPLIED
  name %qname; #IMPLIED
  priority %priority; #IMPLIED
  mode %qname; #IMPLIED
  %space-att;
>

<!ELEMENT xsl:value-of EMPTY>
<!ATTLIST xsl:value-of
  select %expr; #REQUIRED
  disable-output-escaping (yes|no) "no"
>

<!ELEMENT xsl:copy-of EMPTY>
<!ATTLIST xsl:copy-of select %expr; #REQUIRED>

<!ELEMENT xsl:number EMPTY>
<!ATTLIST xsl:number
   level (single|multiple|any) "single"
   count %pattern; #IMPLIED
   from %pattern; #IMPLIED
   value %expr; #IMPLIED
   format %avt; '1'
   lang %avt; #IMPLIED
   letter-value %avt; #IMPLIED
   grouping-separator %avt; #IMPLIED
   grouping-size %avt; #IMPLIED
>

<!ELEMENT xsl:apply-templates (xsl:sort|xsl:with-param)*>
<!ATTLIST xsl:apply-templates
  select %expr; "node()"
  mode %qname; #IMPLIED
>

<!ELEMENT xsl:apply-imports EMPTY>

<!-- xsl:sort cannot occur after any other elements or
any non-whitespace character -->

<!ELEMENT xsl:for-each
 (#PCDATA
  %instructions;
  %result-elements;
  | xsl:sort)*
>
<!ATTLIST xsl:for-each
  select %expr; #REQUIRED
  %space-att;
>

<!ELEMENT xsl:sort EMPTY>
<!ATTLIST xsl:sort
  select %expr; "."
  lang %avt; #IMPLIED
  data-type %avt; "text"
  order %avt; "ascending"   case-order %avt; #IMPLIED
>

<!ELEMENT xsl:if %template;>
<!ATTLIST xsl:if
  test %expr; #REQUIRED
  %space-att;
>

<!ELEMENT xsl:choose (xsl:when+, xsl:otherwise?)>
<!ATTLIST xsl:choose %space-att;>

<!ELEMENT xsl:when %template;>
<!ATTLIST xsl:when
  test %expr; #REQUIRED
  %space-att;
>

<!ELEMENT xsl:otherwise %template;>
<!ATTLIST xsl:otherwise %space-att;>

<!ELEMENT xsl:attribute-set (xsl:attribute)*>
<!ATTLIST xsl:attribute-set
  name %qname; #REQUIRED
  use-attribute-sets %qnames; #IMPLIED
>

<!ELEMENT xsl:call-template (xsl:with-param)*>
<!ATTLIST xsl:call-template
  name %qname; #REQUIRED
>

<!ELEMENT xsl:with-param %template;>
<!ATTLIST xsl:with-param
  name %qname; #REQUIRED
  select %expr; #IMPLIED
>

<!ELEMENT xsl:variable %template;>
<!ATTLIST xsl:variable
  name %qname; #REQUIRED
  select %expr; #IMPLIED
>

<!ELEMENT xsl:param %template;>
<!ATTLIST xsl:param
  name %qname; #REQUIRED
  select %expr; #IMPLIED
>

<!ELEMENT xsl:text (#PCDATA)>
<!ATTLIST xsl:text
  disable-output-escaping (yes|no) "no"
>

<!ELEMENT xsl:processing-instruction %char-template;>
<!ATTLIST xsl:processing-instruction
  name %avt; #REQUIRED
  %space-att;
>

<!ELEMENT xsl:element %template;>
<!ATTLIST xsl:element
  name %avt; #REQUIRED
  namespace %avt; #IMPLIED
  use-attribute-sets %qnames; #IMPLIED
  %space-att;
>

<!ELEMENT xsl:attribute %char-template;>
<!ATTLIST xsl:attribute
  name %avt; #REQUIRED
  namespace %avt; #IMPLIED
  %space-att;
>

<!ELEMENT xsl:comment %char-template;>
<!ATTLIST xsl:comment %space-att;>

<!ELEMENT xsl:copy %template;>
<!ATTLIST xsl:copy
  %space-att;
  use-attribute-sets %qnames; #IMPLIED
>

<!ELEMENT xsl:message %template;>
<!ATTLIST xsl:message
  %space-att;
  terminate (yes|no) "no"
>

<!ELEMENT xsl:fallback %template;>
<!ATTLIST xsl:fallback %space-att;>

D Примеры (пояснения к спецификации)

D.1 Пример документа

В данном примере представлен стиль для преобразования документа, соответствующего простому DTD, в XHTML [XHTML]. Содержимое DTD:

<!ELEMENT doc (title, chapter*)>
<!ELEMENT chapter (title, (para|note)*, section*)>
<!ELEMENT section (title, (para|note)*)>
<!ELEMENT title (#PCDATA|emph)*>
<!ELEMENT para (#PCDATA|emph)*>
<!ELEMENT note (#PCDATA|emph)*>
<!ELEMENT emph (#PCDATA|emph)*>

Содержимое стиля:

<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns="http://www.w3.org/TR/xhtml1/strict">

<xsl:strip-space elements="doc chapter section"/>
<xsl:output
   method="xml"
   indent="yes"
   encoding="iso-8859-1"
/>

<xsl:template match="doc">
 <html>
   <head>
     <title>
       <xsl:value-of select="title"/>
     </title>
    </head>
   <body>
     <xsl:apply-templates/>
   </body>
  </html>
 </xsl:template>

<xsl:template match="doc/title">
  <h1>
     <xsl:apply-templates/>
  </h1>
</xsl:template>

<xsl:template match="chapter/title">
  <h2>
    <xsl:apply-templates/>
  </h2>
</xsl:template>

<xsl:template match="section/title">
  <h3>
    <xsl:apply-templates/>
  </h3>
</xsl:template>

<xsl:template match="para">
  <p>
    <xsl:apply-templates/>
  </p>
</xsl:template>

<xsl:template match="note">
  <p class="note">
    <b>NOTE: </b>
    <xsl:apply-templates/>
   </p>
</xsl:template>

<xsl:template match="emph">
   <em>
    <xsl:apply-templates/>
  </em>
</xsl:template>

</xsl:stylesheet>

Со следующим входным документом

<!DOCTYPE doc SYSTEM "doc.dtd">
<doc>
<title>Document Title</title>
<chapter>
<title>Chapter Title</title>
<section>
<title>Section Title</title>
<para>This is a test.</para>
<note>This is a note.</note>
</section>
<section>
<title>Another Section Title</title>
<para>This is <emph>another</emph> test.</para>
<note>This is another note.</note>
</section>
</chapter>
</doc>

стиль должен дать следующий результат

<?xml version="1.0" encoding="iso-8859-1"?>

<html xmlns="http://www.w3.org/TR/xhtml1/strict">
<head> <title>Document Title</title>
</head>
<body>
<h1>Document Title</h1>
<h2>Chapter Title</h2>
<h3>Section Title</h3>
<p>This is a test.</p>
<p class="note">
<b>NOTE: </b>This is a note.</p>
<h3>Another Section Title</h3>
<p>This is <em>another</em> test.</p>
<p class="note">
<b>NOTE: </b>This is another note.</p>
</body>
</html>

D.2 Пример данных

Для неких данных, представленных в формате XML, данный пример показывает преобразование с помощью трех различных стилей XSLT чтобы получить три различных представления этих данных в форматах HTML, SVG и VRML.

Входные данные:

<sales>

        <division id="North">
                <revenue>10</revenue>
                <growth>9</growth>
                <bonus>7</bonus>
        </division>

        <division id="South">
                <revenue>4</revenue>
                <growth>3</growth>

                <bonus>4</bonus>
        </division>

        <division id="West">
                <revenue>6</revenue>
                <growth>-1.5</growth>
                <bonus>2</bonus>
        </division>

</sales>

Далее приводится стиль, который, используя упрощенный синтаксис, описанный в главе [2.3 Фиксированный конечный элемент как стиль], преобразует эти данные в формат HTML:

<html xsl:version="1.0"
      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
      lang="en">
    <head>
    <title>Sales Results By Division</title>
    </head>
    <body>
    <table border="1">
        <tr>
         <th>Division</th>
        <th>Revenue</th>
        <th>Growth</th>
        <th>Bonus</th>
         </tr>
        <xsl:for-each select="sales/division">
        <!-- order the result by revenue -->
        <xsl:sort select="revenue"
              data-type="number"
              order="descending"/>
        <tr>
            <td>
            <em><xsl:value-of select="@id"/></em>
            </td>
            <td>
            <xsl:value-of select="revenue"/>
            </td>
            <td>
             <!-- highlight negative growth in red -->
            <xsl:if test="growth &lt; 0">
                 <xsl:attribute name="style">
                 <xsl:text>color:red</xsl:text>
                 </xsl:attribute>
            </xsl:if>
            <xsl:value-of select="growth"/>
            </td>
            <td>
            <xsl:value-of select="bonus"/>
            </td>
        </tr>
        </xsl:for-each>
    </table>
    </body>
</html>

Полученный HTML документ:

<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>Sales Results By Division</title>
</head>
<body>
<table border="1">
<tr>
<th>Division</th><th>Revenue</th><th>Growth</th><th>Bonus</th>
</tr>
<tr>
<td><em>North</em></td><td>10</td><td>9</td><td>7</td>
</tr>
<tr>
<td><em>West</em></td><td>6</td><td style="color:red">-1.5</td><td>2</td>
</tr>
<tr> <td><em>South</em></td><td>4</td><td>3</td><td>4</td>
</tr>
</table>
</body>
</html>

Следующий стиль преобразует данные в SVG:

<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns="http://www.w3.org/Graphics/SVG/SVG-19990812.dtd">

<xsl:output method="xml" indent="yes" media-type="image/svg"/>

<xsl:template match="/">

<svg width = "3in" height="3in">
    <g style = "stroke: #000000">
        <!-- draw the axes -->
        <line x1="0" x2="150" y1="150" y2="150"/>
        <line x1="0" x2="0" y1="0" y2="150"/>
        <text x="0" y="10">Revenue</text>
        <text x="150" y="165">Division</text>
        <xsl:for-each select="sales/division">
        <!-- define some useful variables -->

        <!-- the bar's x position -->
        <xsl:variable name="pos"
                      select="(position()*40)-30"/>

        <!-- the bar's height -->
         <xsl:variable name="height"
                      select="revenue*10"/>

        <!-- the rectangle -->
        <rect x="{$pos}" y="{150-$height}"
                  width="20" height="{$height}"/>

         <!-- the text label -->
        <text x="{$pos}" y="165">
            <xsl:value-of select="@id"/>
         </text>

        <!-- the bar value -->
        <text x="{$pos}" y="{145-$height}">
            <xsl:value-of select="revenue"/>
        </text>
        </xsl:for-each>
    </g>
</svg>

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

Полученный SVG документ:

<svg width="3in" height="3in"
      xmlns="http://www.w3.org/Graphics/SVG/svg-19990412.dtd">
    <g style="stroke: #000000">
    <line x1="0" x2="150" y1="150" y2="150"/>
     <line x1="0" x2="0" y1="0" y2="150"/>
    <text x="0" y="10">Revenue</text>
    <text x="150" y="165">Division</text>
    <rect x="10" y="50" width="20" height="100"/>
    <text x="10" y="165">North</text>
    <text x="10" y="45">10</text>
    <rect x="50" y="110" width="20" height="40"/>
    <text x="50" y="165">South</text>
     <text x="50" y="105">4</text>
    <rect x="90" y="90" width="20" height="60"/>
    <text x="90" y="165">West</text>
    <text x="90" y="85">6</text>
    </g>
</svg>

Следующий стиль преобразует данные в VRML:

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

<!-- generate text output as mime type model/vrml, using default charset -->
<xsl:output method="text" encoding="UTF-8" media-type="model/vrml"/>

        <xsl:template match="/">#VRML V2.0 utf8

# externproto definition of a single bar element
EXTERNPROTO bar [
  field SFInt32 x
  field SFInt32 y
  field SFInt32 z
  field SFString name
  ]
  "http://www.vrml.org/WorkingGroups/dbwork/barProto.wrl"

# inline containing the graph axes
Inline {
        url "http://www.vrml.org/WorkingGroups/dbwork/barAxes.wrl"
        }

                 <xsl:for-each select="sales/division">
bar {
        x <xsl:value-of select="revenue"/>
        y <xsl:value-of select="growth"/>
        z <xsl:value-of select="bonus"/>
        name "<xsl:value-of select="@id"/>"
        }
                </xsl:for-each>

        </xsl:template>

</xsl:stylesheet>

Полученный VRML документ:

#VRML V2.0 utf8

# externproto definition of a single bar element  EXTERNPROTO bar [
  field SFInt32 x
  field SFInt32 y
  field SFInt32 z
  field SFString name
  ]
  "http://www.vrml.org/WorkingGroups/dbwork/barProto.wrl"

# inline containing the graph axes
Inline {
        url "http://www.vrml.org/WorkingGroups/dbwork/barAxes.wrl"
        }

bar {
        x 10
        y 9
        z 7
        name "North"
        }
                 bar {
        x 4

        y 3
        z 4
        name "South"
        }

bar {         x 6

        y -1.5         z 2
         name "West"
        }

E Благодарности (пояснения к спецификации)

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

  • Daniel Lipkin, Saba
  • Jonathan Marsh, Microsoft
  • Henry Thompson, Университет Эдинбурга
  • Norman Walsh, Arbortext
  • Steve Zilles, Adobe

Данная спецификация была разработана и одобрена для публикации рабочей группой по XSL из W3C. То что рабочая группа одобрила эту спецификацию, не обязательно означает, что ее одобрили все члены группы. В настоящее время членами рабочей группы по XSL являются:

Sharon Adler, IBM (сопредседатель); Anders Berglund, IBM; Perin Blanchard, Novell; Scott Boag, Lotus; Larry Cable, Sun; Jeff Caruso, Bitstream; James Clark; Peter Danielsen, Bell Labs; Don Day, IBM; Stephen Deach, Adobe; Dwayne Dicks, SoftQuad; Andrew Greene, Bitstream; Paul Grosso, Arbortext; Eduardo Gutentag, Sun; Juliane Harbarth, Software AG; Mickey Kimchi, Enigma; Chris Lilley, W3C; Chris Maden, Exemplary Technologies; Jonathan Marsh, Microsoft; Alex Milowski, Lexica; Steve Muench, Oracle; Scott Parnell, Xerox; Vincent Quint, W3C; Dan Rapp, Novell; Gregg Reynolds, Datalogics; Jonathan Robie, Software AG; Mark Scardina, Oracle; Henry Thompson, University of Edinburgh; Philip Wadler, Bell Labs; Norman Walsh, Arbortext; Sanjiva Weerawarana, IBM; Steve Zilles, Adobe (сопредседатель)

F Изменения по внесенным рекомендациям (пояснения к спецификации)

После вынесения предложенной Рекомендации на обсуждение были приняты следующие изменения:

  • В фиксированном конечном элементе, используемом в качестве стиля, обязательным является атрибут xsl:version (см. [2.3 Фиксированный конечный элемент как стиль]).

  • Атрибут data-type в xsl:sort может использовать префиксное имя для того, чтобы указывать тип данных, не определенный в XSLT (см. главу [10 Сортировка]).

G Характеристики для рассмотрения в будущих версиях XSLT (пояснения к спецификации)

Для версий XSLT, которые последуют за XSLT 1.0, рассматривается следующий функционал:

  • выражение при условии;

  • поддержка типов данных и архитипов для XML Schema;

  • поддержка чего-либо похожего на правила типов в исходном представлении XSL;

  • атрибут, задающий пространство имен по умолчанию для имен, используемых в атрибутах XSLT;

  • поддержка ссылок на сущности;

  • поддержка DTD в модели данных;

  • поддержка нотаций в модели данных;

  • способ обратиться в обратном направлении от элемента к тем элементам, которые на него ссылаются (например, с помощью атрибутов IDREF);

  • упрощенный способ получить ID или ключ в другом документе;

  • поддержка регулярных выражений, которые исключают все или что-либо из текстовых узлов, значений атрибутов, названий атрибутов, названий типов элементов;

  • независимое от регистра сравнение;

  • нормализация строк перед сравнением, например, для совместимости символов;

  • функция строка resolve(набор узлов), которая обрабатывает значение аргумента как относительный URI и преобразует его в абсолютный URI, используя базовый URI данного узла;

  • несколько конечных документов;

  • используемый по умолчанию атрибут select для xsl:value-of в текущем узле;

  • атрибут в xsl:attribute, позволяющий управлять нормализацией значения этого атрибута;

  • дополнительные атрибуты в xsl:sort чтобы получить больший контроль над сортировкой, например, над относительным порядком скриптов;

  • способ разместить в конечном дереве текст, взятый из некого ресурса, идентифицируемого с помощью URI;

  • позволить объединение шагов (например, foo/(bar|baz));

  • разрешить использовать для фрагментов конечного дерева все те же операции, которые разрешены для набора узлов;

  • способ группировать вместе следующих друг за другом узлы, имеющие одинаковые нижележащие элементы или атрибуты;

  • свойства, которые бы сделали обработку атрибута HTML style более удобной.

H Словарь (пояснения к спецификации)

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

attribute value template - именованный набор атрибутов
child - непосредственный потомок
conditional processing - обработка при условии
conformance - соответствие спецификации
context node - узел контекста
context node list - контекстный набор узлов
context position - положение в контексте
document element - элемент документа
document type declaration - декларация типа документа, DTD
DTD subset - набор DTD (внутренний, внешний)
element node - узел элемента
escape character - маскировать символ
expanded name - расширенное имя
extension namespace - пространство имен расширений
fallback - откат
forward-compatible processing - обработка в режиме совместимости с последующими версиями
literal result element - фиксированный конечный элемент
location path - путь адресации
named attribute set - именованный набор атрибутов
node set - набор узлов
parsed entity - разобранная сущность
pattern - образец (правила шаблона)
processing instruction - инструкция обработки
production - сценарий (языков XML, XPath)
qualified name - полное имя
result tree - конечное дерево (результат выполнения преобразования)
source tree - начальное дерево (объект преобразования)
standalone document - одиночный документ
stylesheet - стиль оформления
template rule - правило шаблона
top-level element - элемент верхнего уровня
unparsed entity - неразобранная сущность
value-binding element - элемент привязки переменной
variable binding - привязка переменной контекста
vocabulary - словарь форматирования
well-formed - корректный
whitespace - пробельный символ

Если у вас возникли какие-либо замечания, мы будем рады их получить по адресу radik_u@mail.ru.