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

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

Эта проблема решается в XSLT просто и элегантно. Атрибут

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

Пример

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

URI пространства имен языка XHTML —

"http://www.w3.org/1999/xhtml"
; этому языку мы назначим префикс "
xhtml
" и, кроме того, сделаем это пространство пространством имен по умолчанию:

 version="1.0"

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

 xmlns:xhtml="http://www.w3.org/1999/xhtml"

 xmlns="http://www.w3.org/1999/xhtml">

 ...

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

href
и текст, который она содержит. Для удобочитаемости мы также добавим элемент
br
и символ переноса строки

.



Мы чуть позже познакомимся с элементами

xsl:copy
,
xsl:copy-of
и
xsl:text
, пока же скажем, что

копирует в выходящий документ текущий узел, его атрибут

href
(
@href
) и дочерние текстовые узлы (
text()
).

Элемент


выводит символ переноса строки. Элемент

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

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

И, наконец, нам понадобится преобразование для элемента

body
— в него мы включим копию содержимого, а также ссылки, отсортированные в алфавитном порядке:

Links found on this page:

   select=".//xhtml:a[@href and not(xhtml:*)]">

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

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

Для исправления этой ошибки мы выделим шаблон обработки ссылок в отдельный режим

links
:

 ...

Теперь это правило не будет применяться к ссылкам во время копирования содержимого документа, потому что при выполнении инструкции

режим будет пустым, значит шаблон для

xhtml:а
вызываться не будет. Для того чтобы применить его при помощи
xsl:apply-templates
, мы добавим в этот элемент атрибут
mode
:

 select=".//xhtml:a[@href and not(xhtml:*)]"

 mode="links">

Разберем более подробно это определение. Данная инструкция будет применять шаблоны с режимом

links
к узлам, возвращаемым выражением
".//xhtml:a[@href and not (xhtml:*)]"
, отсортированным в алфавитном порядке своих строковых значений. Выражение
".//xhtml:a[@href and not(xhtml:*)]"
возвращает всех потомков текущего узла (путь выборки "
.//
"), которые принадлежат пространству имен
xhtml
, являются элементами с именами
а
, (тест имени "
xhtml:a
"), при этом имеют атрибут
href
и не включают в себя другие элементы (предикат "
[@href and not (xhtml:*)]
").

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

Листинг 5.4. Преобразование, добавляющее перечень ссылок

 version="1.0"

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

 xmlns:xhtml="http://www.w3.org/1999/xhtml"

 xmlns="http://www.w3.org/1999/xhtml">


Links found on this page:




<