<table>
<tr>
<xsclass="underline" apply-templates select="month"/>
</tr>
</table>
</xsclass="underline" template>
Выполняться он будет в следующем контексте (рис. 3.21):
Рис. 3.21. Контекст шаблона элемента summer
Атрибут select элемента xsclass="underline" apply-templates, который присутствует в этом шаблоне, вычисляет новое текущее множество: путь выборки month возвращает все дочерние элементы month текущего узла. Текущим узлом является элемент summer, то есть новое текущее множество будет состоять из трех его дочерних элементов month. Таким образом, процессор будет поочередно выполнять шаблоны в каждом из трех следующих контекстов, показанных на рис. 3.22.
Рис. 3.22. Изменение контекста при выполнении шаблона элемента month
Шаблон, вычисляемый в каждом из этих контекстов, имеет следующий вид:
<xsclass="underline" template match="month">
<td>
<xsclass="underline" value-of select="."/>
</td>
</xsclass="underline" template>
Элемент xsclass="underline" value-of этого шаблона создает в элементе td текстовый узел, значение которого равно строковому значению выражения ".", то есть строковому значению текущего узла, и в каждом случае это будет строковое значение соответствующего элемента month.
Контекст преобразования позволяет более четко определить такие понятия, как "обработка узла", "применение шаблона к узлу" и так далее. Все эти выражения означают одно: выполнение соответствующего шаблона с данным узлом в качестве текущего.
Выполнение преобразования
Несмотря на полную свободу в порядке выполнения шаблонов, правила изменения контекста и компоновки результирующего дерева, спецификация XSLT оговаривает очень четко — это делает XSLT весьма гибким языком, программы на котором при этом выполняются совершенно детерминированным образом.
Типовой процесс выполнения преобразования согласно спецификации включает следующие стадии:
□ дерево выходящего документа создается путем обработки множества, состоящего из единственного узла — текущего узла дерева;
□ результатом применения шаблонов к обрабатываемому множеству узлов является объединение фрагментов деревьев, которые являются результатами обработки каждого из узлов множества;
□ каждый из узлов обрабатываемого множества преобразуется следующим образом:
• из всех шаблонов, определенных в данном преобразовании, выбираются шаблоны, соответствующие данному узлу (соответствие определяется паттерном, указанным в атрибуте match элемента xsclass="underline" template);
• из этих шаблонов выбирается наиболее подходящий;
• выбранный шаблон выполняется в контексте обрабатываемого множества как текущего множества узлов и обрабатываемого узла как текущего узла;
□ если шаблон содержит инструкции xsclass="underline" apply-templates или xsclass="underline" foreach, которые дополнительно выбирают узлы для обработки, процесс рекурсивно продолжается до тех пор, пока обрабатываемое множество будет содержать хотя бы один узел.
В общих чертах этот процесс был продемонстрирован на примере, приведенном в описании контекста преобразования. Сейчас мы завершим картину, показав, как в каждом из шаблонов будут создаваться результирующие фрагменты деревьев и как они затем будут "сращиваться" в дерево выходящего документа.
На сей раз, мы начнем с самых "глубоких" шаблонов — шаблонов, обрабатывающих элементы month.
<xsclass="underline" template match="month">
<td>
<xsclass="underline" value-of select="."/>
</td>
</xsclass="underline" template>
Каждый из них создает результирующий фрагмент дерева следующего вида (рис. 3.23).
Рис. 3.23. Результат обработки элемента month
Шаблоны к элементам month применяются элементом xsclass="underline" apply-templates при обработке элемента summer соответствующим шаблоном:
<xsclass="underline" template match="summer">
<table>
<tr>
<xsclass="underline" apply-templates select="month"/>
</tr>
</table>
</xsclass="underline" template>
Результатом выполнения xsclass="underline" apply-templates будет объединение результирующих фрагментов деревьев, которые получатся при обработке элементов month. Таким образом, результирующий фрагмент этого шаблона будет "собран" в следующем виде (рис. 3.24):
Рис. 3.24. Результат обработки элемента summer
Пунктиром выделены результирующие фрагменты деревьев, сгенерированные при обработке элементов month; эти фрагменты объединяются и используются при создании фрагмента дерева, являющегося результатом обработки элемента summer.
Этот результат, в свою очередь, используется в главном шаблоне — шаблоне, который обрабатывает корневой элемент:
<xsclass="underline" template match="/">
<html>
<head>
<title>Summer</title>
</head>
<body>
<xsclass="underline" apply-templates select="summer"/>
</body>
</html>
</xsclass="underline" template>
Сгенерированный при обработке элемента summer результирующий фрагмент дерева включается в корневом шаблоне в элемент body (рис.3.25).
Рис. 3.25. Результат обработки корневого узла
Пунктиром выделен результирующий фрагмент дерева, который был получен при обработке элемента summer.
Результирующий фрагмент дерева, полученный в результате обработки корневого узла, является деревом выходящего документа. В чистом XSLT это и есть результат выполнения преобразования. Для того чтобы получить физическую интерпретацию — в данном случае HTML-документ, дерево сериализуется, обращаясь в следующий выходящий документ.
<html>
<head>
<title>Summer</title>
</head>
<body>
<table>
<tr>
<td>June</td>
<td>July</td>
<td>August</td>
</tr>
</table>
</body>
</html>
Надо сказать, что спецификация языка XSLT не оговаривает, в каком именно порядке процессоры должны выполнять шаблонные правила — главное, чтобы результат преобразования совпадал с результатом, полученным при обработке приведенным выше способом. На практике это означает, что разработчикам совершенно необязательно знать, как именно конкретный процессор применяет правила — достаточно понимать принципы шаблонной обработки. В этом одно из главных достоинств XSLT как языка, не имеющего побочных эффектов.