Три шага этого преобразования продемонстрированы на рис. 5.1.
Рис. 5.1. Процесс преобразования
Здесь слева показан текущий список узлов, посередине — дерево документа с выделенным пунктиром текущим узлом, справа — генерируемое выходящее дерево.
Результатом этого преобразования будет документ:
<b>text</b>
Рассмотрим чуть более сложное преобразование документа:
<para>
<bold>text1</bold>
<para>
<bold>text2</bold>
</para>
</para>
Порядок
действий в этом случае будет приблизительно следующим.
□ Первым обрабатывается корневой узел. Процессор применяет шаблоны к дочерним узлам (вернее к одному дочернему узлу — элементу
para
).
□ Шаблон, обрабатывающий элемент para, создает в выходящем документе элемент p и применяет шаблоны к своим дочерним узлам — на этот раз их два,
bold
и
para
.
□ Шаблон, обрабатывающий элемент
bold
, создает в выходящем документе элемент
b
и текстовый узел со значением "
text1
".
□ Шаблон, обрабатывающий элемент
para
, создает в выходящем дереве узел
p
и применяет шаблоны к дочерним узлам.
□ Единственным дочерним узлом элемента
para
является элемент
bold
.
□ Шаблон, обрабатывающий этот элемент
bold
, создает в выходящем документе элемент
b
и текстовый узел со значением "
text2
".
Процесс преобразования показан на рис. 5.2.
Рис. 5.2. Процесс преобразования
Результатом этого преобразования будет документ:
<b>text1</b>
<b>text2</b>
Атрибут
select
элемента
xsl:apply-templates
позволяет выбирать, к каким именно узлам будет применяться этот шаблон. Значение
select
— это XPath-выражение, которое должно возвращать множество узлов. В случае, если атрибут
select
указан, шаблоны будут поочередно применяться к каждому из узлов выбранного множества.
Пример
Если при обработке элементов para мы хотим обрабатывать только дочерние элементы
bold
и никакие другие, шаблон обработки элементов
para
будет записан следующим образом:
<xsl:template match="para">
<xsl:apply-templates select="bold"/>
</xsl:template>
Результатом обработки документа
<para>
<bold>text1</bold>
<para>
<bold>text2</bold>
</para>
</para>
будет теперь
<b>text1</b>
Элемент
para
, который во входящем документе включен в другой элемент
para
, не будет обработан по той простой причине, что он не вошел во множество, выбранное XPath-выражением "
bold
".
В то же время, если мы запишем
<xsl:template match="para">
<xsl:apply-templates select="bold|para"/>
</xsl:template>
то результат будет таким же, как и прежде:
<b>text1</b>
<b>text2</b>
Следует хорошо понимать разницу между атрибутом
select
элемента
xsl:apply-templates
и атрибутом
match
элемента
xsl:template
. Атрибут
match
содержит не XPath-выражение, а паттерн XSLT; в отличие от атрибута select в
xsl:apply-templates
он не выбирает никакого множества узлов, он используется только для того, чтобы проверить, может ли данный узел обрабатываться этим шаблоном или нет.
Атрибут
select
элемента
xsl:apply-templates
наоборот, содержит не паттерн, а выражение, единственным требованием к которому является то, что оно должно возвращать множество узлов. Например, некорректным будет определение вида
<xsl:apply-templates select="para+1"/>
поскольку выражение
para+1
не может возвратить множество узлов.
Кроме этого требования, никаких других ограничений на выражения в этом атрибуте нет. В нем можно использовать переменные, содержащие множества узлов, функции, возвращающие множества узлов (например, такие, как
id
или
key
), выражения с операциями над множествами (именно таким выражением — выражением объединения было выражение
bold|para
), пути выборки, фильтрующие выражения, в общем, любые выражения, которые только могут возвращать множества. Например, для того, чтобы обработать содержимое произвольного внешнего XML-документа, в атрибуте
Очень часто в преобразованиях требуется обрабатывать одни и те же узлы, но разными способами. Типичным примером такого рода задачи является генерация оглавления документа вместе с преобразованием его содержимого. Очевидно, что просто шаблонами здесь не обойтись, и чтобы не получить другой результат, нужно каким-то образом указывать, что по-другому должна вестись и обработка.
Эта проблема решается в XSLT просто и элегантно. Атрибут
mode
элемента xsl:template задает режим этого шаблона. Точно такой же атрибут есть у элемента
xsl:apply-templates
: в этом элементе он устанавливает режим обработки. При выполнении
xsl:apply-templates
процессор будет применять только те шаблоны преобразования, режим которых совпадает с выбранным режимом обработки.
Пример
В качестве примера приведем преобразование, которое добавляет в XHTML-файл перечень текстовых ссылок, обнаруженных в этом документе. Грубо говоря, XHTML — это XML-версия языка HTML, а значит XSLT вполне подходит для обработки XHTML-документов.