Книга: Технология XSLT

Элемент xsl:apply-templates

Элемент xsl:apply-templates

Синтаксис этого элемента выглядит следующим образом:

<xsl:apply-templates
 select="выражение"
 mode="режим">
 <!-- Содержимое: несколько элементов xsl:sort или xsl:with-param -->
</xsl:apply-templates>

Элемент xsl:apply-templates применяет шаблонные правила к узлам, которые возвращаются выражением, указанным в атрибуте select. Если атрибут select опущен, то xsl:apply-templates применяет шаблонные правила ко всем дочерним узлам текущего узла, то есть

<xsl:apply-templates/>

равносильно

<xsl:apply-templates select="child::node()"/>

Атрибут mode используется для указания режима, в котором должны применяться шаблоны — мы поговорим о различных режимах чуть позже.

Прежде чем двигаться дальше, опишем более подробно, что означает "применить шаблон" (англ. apply — применить, template — шаблон). Применение шаблонов — это составная часть обработки документа, которая может быть описана следующим порядком действий.

? На первом шаге процессор вычисляет выражение, указанное в атрибуте select. Его значением должно быть множество узлов. Полученное множество узлов упорядочивается и становится текущим списком узлов контекста преобразования.

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

? Дерево, которое является результатом выполнения шаблона, добавляется в выходящее дерево.

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

Листинг 5.3. Преобразование с para и bold — версия 2

<xsl:stylesheet
 version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:template match="bold">
  <b><xsl:value-of select="."/></b>
 </xsl:template>
 <xsl:template match="para">
  <p><xsl:apply-templates</p>
 </xsl:template>
</xsl:stylesheet>

Проследим за процессом выполнения этого преобразования.

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

? Шаблон, соответствующий элементу para, создает элемент p, содержимым которого будет результат выполнения инструкции xsl:apply-templates, то есть результат применения шаблонов к дочерним узлам текущего узла — элемента para.

? Единственным дочерним узлом элемента para является элемент bold. Процессор изменит контекст так, что текущий список узлов будет содержать только элемент bold и выполнит соответствующее шаблонное правило, которое создаст элемент b и включит в него узел, вычисленный инструкцией <xsl:value-of select="."/>, то есть текстовый узел со строковым значением текущего узла, элемента bold.

Три шага этого преобразования продемонстрированы на рис. 5.1.


Рис. 5.1. Процесс преобразования

Здесь слева показан текущий список узлов, посередине — дерево документа с выделенным пунктиром текущим узлом, справа — генерируемое выходящее дерево.

Результатом этого преобразования будет документ:

<p><b>text</b></p>

Рассмотрим чуть более сложное преобразование документа:

<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. Процесс преобразования

Результатом этого преобразования будет документ:

<p>
 <b>text1</b>
 <p>
  <b>text2</b>
 </p>
</p>

Атрибут select элемента xsl:apply-templates позволяет выбирать, к каким именно узлам будет применяться этот шаблон. Значение select — это XPath-выражение, которое должно возвращать множество узлов. В случае, если атрибут select указан, шаблоны будут поочередно применяться к каждому из узлов выбранного множества.

Пример

Если при обработке элементов para мы хотим обрабатывать только дочерние элементы bold и никакие другие, шаблон обработки элементов para будет записан следующим образом:

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

Результатом обработки документа

<para>
 <bold>text1</bold>
 <para>
  <bold>text2</bold>
 </para>
</para>

будет теперь

<p>
 <b>text1</b>
</p>

Элемент para, который во входящем документе включен в другой элемент para, не будет обработан по той простой причине, что он не вошел во множество, выбранное XPath-выражением "bold". В то же время, если мы запишем

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

то результат будет таким же, как и прежде:

<p>
 <b>text1</b>
 <p>
  <b>text2</b>
 </p>
</p>

Следует хорошо понимать разницу между атрибутом 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-документа, в атрибуте select элемента xsl:apply-template следует использовать функцию document.

Пример

Объявление вида

<xsl:apply-templates select="document('a.xml')//para"/>

применит шаблоны ко всем элементам para документа a.xml.

Оглавление книги

Оглавление статьи/книги

Генерация: 0.060. Запросов К БД/Cache: 0 / 0
поделиться
Вверх Вниз