Рассмотрим следующий простой пример.
Листинг 5.1. Входящий документ
text
Попробуем написать пару шаблонов, которые будут изменять имена элементов paraи boldна pи bсоответственно. Сначала напишем преобразование для bold:
В этом правиле создается элемент b, в который включается текстовое значение текущего узла (то есть, обрабатываемого элемента bold). Применив это преобразование к входящему документу, мы получим следующий результат:
text
Как говорят математики, что и требовалось. Попробуем проделать тот же трюк с элементом paraи создадим преобразование, включающее оба правила.
Листинг 5.2. Преобразование с para и bold — версия 1
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
На этот раз вместо ожидаемого результата вида
text
мы получим
text
Попробуем ответить на три вопроса: кто виноват, что делать и куда делся элемент b.
Для ответа на вопрос, куда делся элемент b, пожалуй, необходимо будет пояснить, что же именно происходит при преобразовании этого документа. Последовательно рассмотрим стадии этого процесса.
□ Процессор начинает обработку с корневого узла дерева. Он выбирает шаблон, соответствующий этому узлу. В нашем преобразовании такого шаблона нет, значит, процессор применит к корню шаблонное правило, определенное по умолчанию ( см. раздел "Встроенные шаблоны" данной главы ).
□ По умолчанию шаблонное правило корневого узла обрабатывает все дочерние узлы. В нашем документе единственным дочерним узлом корня будет элемент para.
□ Для элемента paraв нашем преобразовании задан шаблон, который и будет применен к этому элементу.
□ В соответствии с этим шаблоном, процессор создаст элемент pи включит в него текстовое значение выражения " .". Как мы знаем, выражение " ." является сокращенной формой выражения " self::node()", которое возвратит текущий узел. Таким образом, элемент вычислит и возвратит строковое значение текущего узла, то есть узла para. Строковым значением элемента является конкатенация всех его текстовых потомков. Единственным текстовым потомком нашего para является текстовый узел со значением " text" и вот он-то и выводится между открывающим и закрывающим тегами созданного элемента p.
Таким образом, элемент b"потерялся" потому, что шаблон для boldпросто не вызывался. Виноваты, естественно, мы сами, поскольку не включили его вызов. Осталось только разобраться, как можно вызвать шаблон для обработки элемента bold.
Ответ на этот вопрос предельно прост — для вызова неименованных шаблонных правил В XSLT используется элемент xsl:apply-templates.
Элемент xsl:apply-templates
Синтаксис этого элемента выглядит следующим образом:
select=" выражение "
mode=" режим ">
Элемент xsl:apply-templatesприменяет шаблонные правила к узлам, которые возвращаются выражением, указанным в атрибуте select. Если атрибут selectопущен, то xsl:apply-templatesприменяет шаблонные правила ко всем дочерним узлам текущего узла, то есть
равносильно
Атрибут modeиспользуется для указания режима, в котором должны применяться шаблоны — мы поговорим о различных режимах чуть позже.
Прежде чем двигаться дальше, опишем более подробно, что означает "применить шаблон" (англ. apply — применить, template — шаблон). Применение шаблонов — это составная часть обработки документа, которая может быть описана следующим порядком действий.
□ На первом шаге процессор вычисляет выражение, указанное в атрибуте select. Его значением должно быть множество узлов. Полученное множество узлов упорядочивается и становится текущим списком узлов контекста преобразования.
□ Для каждого из узлов этого списка процессор находит наиболее подходящий шаблон для обработки. Процессор делает этот узел текущим и затем выполняет в измененном контексте выбранное шаблонное правило.
□ Дерево, которое является результатом выполнения шаблона, добавляется в выходящее дерево.
Применительно к нашему примеру с paraи bold, мы можем изменить преобразование так, что в создаваемый элемент p будет включаться не текстовое значение элемента para, а результат обработки его дочерних узлов.
Листинг 5.3. Преобразование с para и bold — версия 2
version="1.0"
Читать дальше