Технология XSLT — страница 11 из 66

преобразования

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

Контекст преобразования

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

Контекст преобразования тесно связан с контекстом вычисления выражений:

□ текущий узел контекста преобразования соответствует контекстному узлу вычисления выражений;

□ позиция текущего узла в текущем обрабатываемом множестве соответствует позиции контекста вычисления выражений;

□ размер текущего множества узлов соответствует размеру контекста вычисления выражений.

Контекст преобразования может изменяться только двумя элементами —

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

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

Листинг 3.29. Входящий документ

June

July

August

Этому документу соответствует следующее дерево (рис. 3.19):

Рис. 3.19. Дерево входящего документа

Листинг 3.30. Преобразование

 version="1.0"

 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">


Summer




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

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

Summer

Тело этого шаблона выполняется в том самом изначальном контексте, о котором мы только что упомянули: текущее множество состоит из корневого узла, он же является и текущим узлом. Мы можем показать контекст, выделяя текущее множество, пунктиром, а текущий узел — полужирной линией (рис. 3.20).

Рис. 3.20. Первоначальный контекст преобразования

Атрибут

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

При выполнении элемента

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

сведется к выполнению шаблона, обрабатывающего элемент

summer
. Этот шаблон выглядит следующим образом:

Выполняться он будет в следующем контексте (рис. 3.21):

Рис. 3.21. Контекст шаблона элемента

summer

Атрибут

select
элемента
xsl:apply-templates,
который присутствует в этом шаблоне, вычисляет новое текущее множество: путь выборки
month
возвращает все дочерние элементы
month
текущего узла. Текущим узлом является элемент
summer
, то есть новое текущее множество будет состоять из трех его дочерних элементов
month
. Таким образом, процессор будет поочередно выполнять шаблоны в каждом из трех следующих контекстов, показанных на рис. 3.22.

Рис. 3.22. Изменение контекста при выполнении шаблона элемента

month

Шаблон, вычисляемый в каждом из этих контекстов, имеет следующий вид:

Элемент

xsl:value-of
этого шаблона создает в элементе
td
текстовый узел, значение которого равно строковому значению выражения "
.
", то есть строковому значению текущего узла, и в каждом случае это будет строковое значение соответствующего элемента
month
.

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

Выполнение преобразования

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

Типовой процесс выполнения преобразования согласно спецификации включает следующие стадии:

□ дерево выходящего документа создается путем обработки множества, состоящего из единственного узла — текущего узла дерева;

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

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

 • из всех шаблонов, определенных в данном преобразовании, выбираются шаблоны, соответствующие данному узлу (соответствие определяется паттерном, указанным в атрибуте

match
элемента
xsl:template
);

 • из этих шаблонов выбирается наиболее подходящий;

 • выбранный шаблон выполняется в контексте обрабатываемого множества как текущего множества узлов и обрабатываемого узла как текущего узла;

□ если шаблон содержит инструкции

xsl:apply-templates
или
xsl:foreach
, которые дополнительно выбирают узлы для обработки, процесс рекурсивно продолжается до тех пор, пока обрабатываемое множество будет содержать хотя бы один узел.

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

На сей раз, мы начнем с самых "глубоких" шаблонов — шаблонов, обрабатывающих элементы

month
.

Каждый из них создает результирующий фрагмент дерева следующего вида (рис. 3.23).

Рис. 3.23. Результат обработки элемента month

Шаблоны к элементам

month
применяются элементом
xsl:apply-templates
при обработке элемента
summer
соответствующим шаблоном:


Результатом выполнения

xsl:apply-templates
будет объединение результирующих фрагментов деревьев, которые получатся при обработке элементов
month
. Таким образом, результирующий фрагмент этого шаблона будет "собран" в следующем виде (рис. 3.24):

Рис. 3.24. Результат обработки элемента

summer

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

month
; эти фрагменты объединяются и используются при создании фрагмента дерева, являющегося результатом обработки элемента
summer
.

Этот результат, в свою очередь, используется в главном шаблоне — шаблоне, который обрабатывает корневой элемент:

Summer

Сгенерированный при обработке элемента

summer
результирующий фрагмент дерева включается в корневом шаблоне в элемент
body
(рис.3.25).

Рис. 3.25. Результат обработки корневого узла

Пунктиром выделен результирующий фрагмент дерева, который был получен при обработке элемента

summer
.

Результирующий фрагмент дерева, полученный в результате обработки корневого узла, является деревом выходящего документа. В чистом XSLT это и есть результат выполнения преобразования. Для того чтобы получить физическую интерпретацию — в данном случае HTML-документ, дерево сериализуется, обращаясь в следующий выходящий документ.

Листинг 3.31. Выходящий документ проведённого преобразования

Summer

JuneJulyAugust

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

Глава 4