Все элементы XSLT можно разделить на две группы: элементы основные и элементы дополнительные. Это разделение очень условно, ничего подобного в спецификации языка XSLT нет, однако, мы будем им пользоваться, считая основными элементами те элементы XSLT, которые непосредственно отвечают за создание узлов выходящего дерева или обеспечивают контроль над этим процессом. К дополнительным элементам мы будем относить все остальные элементы XSLT.
Таким образом, множество основных элементов будет включать в себя следующее:
□
xsl:element
— создание в выходящем дереве узла элемента;
□
xsl:attribute
— создание в выходящем дереве узла атрибута;
□
xsl:attribute-set
— определение именованного набора атрибутов;
□
xsl:text
— создание текстового узла;
□
xsl:value-of
— создание текстового узла по результатам вычисления выражения;
□
xsl:comment
— создание узла комментария;
□
xsl:processing-instruction
— создание узла инструкции по обработке;
□
xsl:copy
— копирование текущего узла вместе с его узлами пространств имен;
□ x
sl:copy-of
— копирование результата вычисления выражения;
□
xsl:if
— условная обработка;
□
xsl:choose
, xsl:when
и xsl:otherwise
— выбор одной из нескольких альтернатив согласно некоторым условиям;
□
xsl:for-each
— итеративная обработка множества узлов.
В четвертой главе мы уже разобрали один из способов создания в выходящем документе узлов элементов, а именно — использование литеральных элементов результата, которые в неизменном виде копируются процессором в выходящее дерево. Этот способ прост, понятен и удобен, однако есть две основные проблемы, которые он не может решить.
□ Что, если в выходящем документе требуется создать элемент с заранее неизвестным (например, вычисляемым во время выполнения) именем?
□ Как создать элемент, принадлежащий пространству имен, известному обрабатывающему процессору?
Поясним на примерах суть и той и другой проблемы.
Представим себе входящий документ вида
который нужно преобразовать во что-нибудь наподобие
<а>
а>
Совершенно очевидно, что литеральными элементами тут не обойдешься — мы не знаем заранее имена элементов выходящего документа, ибо они определяются значениями атрибутов входящего.
Представим теперь, что нам в XSLT-преобразовании необходимо сгенерировать другое XSLT-преобразование. Скажем из элемента вида
нужно получить шаблон
Беда в том, что литеральные элементы не могут быть использованы для создания, скажем, элемента
xsl:template
по той причине, что любой элемент с локальной частью имени template
, принадлежащий пространству имен XSLT будет рассматриваться процессором, как элемент самого преобразования. Очевидно, что
будет некорректным определением. He поможет и смена префикса, ведь принадлежность пространству имен определяется не им.
Для того чтобы решить эти проблемы (главным образом, первую), XSLT предоставляет возможность создавать узлы элементов при помощи элемента
xsl:element
.
Синтаксическая конструкция этого элемента задается следующим образом:
name="{имя}"
namespace="{пространство имен}
"use-attribute-sets="имена">
Здесь обязательный атрибут
name
указывает имя создаваемого элемента. Этот атрибут может содержать шаблон значения, а значит, имя элемента может быть вычислено во время выполнения.
Атрибут
namespace
указывает URI пространства имен создаваемого элемента. Точно так же, как и name, этот атрибут может содержать шаблон значения, что позволяет вычислять пространство имен создаваемого элемента при помощи выражений.
Атрибут
use-attribute-sets
перечисляет имена наборов атрибутов, которые должны быть включены в создаваемый элемент.
Содержимым
xsl:element
является шаблон, который выполняется процессором и затем включается в создаваемый элемент.
Предположим, мы хотим поменять имя каждого элемента на значение его первого атрибута и наоборот.
В этом примере код
...
создает элемент, именем которого становится значение выражения @*
, указанного в виде шаблона значения атрибута name
. Это выражение выбирает множество, состоящее из узлов атрибутов текущего элемента, а если привести его к строке, в результате получится текстовое значение первого атрибута элемента.
Подобным образом выбирается имя атрибута создаваемого элемента и его значение.
Вычисленное значение атрибута
name
может задавать и расширенное имя элемента, то есть иметь форму префикс:имя
. В этом случае элемент будет создаваться в том пространстве имен, которое соответствует указанному префиксу, например
создаст элемент вида
Заметим, что элемент вида
даст тот же результат.
Другим способом указания пространства имен при использовании элемента
xsl:element
является использование атрибута namespace
. Например, для предыдущего случая мы могли бы записать
name="template"
namespace="http://www.w3.org/1999/XSL/Transform"/>
и получить в итоге
что эквивалентно результату предыдущего примера, хоть и различается внешне.
Атрибут
namespace
тоже может быть сконструирован на этапе выполнения, например:
name="template"
namespace="{concat('http://www.w3.org/', 2001 - 2, '/XSL/Transform')}"/>
что также даст элемент
template
, принадлежащий пространству имен XSLT.
Для того чтобы разобраться в приоритетах атрибутов
name
и namespace
на определение пространства имен, приведем несколько правил, которые пояснят этот процесс.
□ Если в элементе
xsl:element
определен атрибут namespace
, то создаваемый элемент будет принадлежать пространству имен с URI, который будет значением этого атрибута. Если значением атрибута namespace
будет пустая строка, создаваемый элемент будет принадлежать нулевому пространству имен. Как правило, процессоры используют префикс, указанный в имени атрибутом name
, но, вместе с тем, они не обязаны так делать. Поэтому в общем случае следует ожидать, что префикс может быть любым.
□ Если в элементе
xsl:element
не определен атрибут namespace
, но имя, заданное в атрибуте name имеет префикс, то создаваемый элемент будет принадлежать соответствующему этому префиксу пространству имен. Однако и в этом случае не гарантируется, что префикс создаваемого элемента будет таким, каким он был задан в атрибуте name
.
□ В случае, если в элементе
xsl:element
не определен атрибут namespace
и имя, заданное в атрибуте name не имеет префикса, создаваемый элемент будет принадлежать пространству имен, которое действует для создающего элемента xsl:element
по умолчанию.
Повторим еще раз, что во всех трех случаях сказать что-либо достоверно о префиксе создаваемого элемента нельзя — префикс с точки зрения пространств имен не является значащей частью имени элемента. Вместе с тем, на практике процессоры, как правило, используют префикс, указанный в атрибуте
name
, или не используют префикс вообще, если префикс в name
указан не был.
Приведем несколько примеров.
Для начала покажем, что, согласно первому правилу, атрибут
namespace
имеет наивысший приоритет при определении пространства имен выходящего элемента. Рассмотрим следующее преобразование.
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
name="xsl:html"
namespace="http://www.w3.org/1999/xhtml"/>
В выделенном элементе
xsl:element
пространство имен создаваемого элемента указано вроде бы два раза: в виде значения атрибута namespace
и в виде префикса имени ("xsl
"). Результат будет выглядеть следующим образом:
Процессор использовал пространство имен, указанное в атрибуте
namespace
, локальную часть имени, заданного атрибутом name ("html
"), а также префикс (только префикс, но не связанное с ним пространство имен) этого имени ("xsl
").
В свою очередь конструкция вида
создаст элемент
что на самом деле эквивалентно просто
.
Таким образом, атрибут
namespace
наиболее приоритетен для определения пространства имен создаваемого элемента. Обратимся теперь к случаю, когда этот атрибут опущен в xsl:element
. Объявление вида
создаст элемент
Как видим, отсутствие
namespace
и namespace=""
— не одно и то же.
Рассмотрим теперь случай, когда нет ни атрибута
namespace
, ни префикса в name
:
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
Результатом этого преобразования будет документ, состоящий из одного пустого элемента
html
:
Мы специально привели все преобразование целиком, чтобы показать, что выходящий элемент будет принадлежать нулевому пространству имен тогда и только тогда, когда для него не было объявлено пространства имен по умолчанию. Попробуем посмотреть, что получится, если пространство имен по умолчанию будет объявлено:
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
Результатом в этот раз будет элемент с локальной частью имени "
html
", принадлежащий пространству имен с URI "http://www.w3.org/1999/xhtml
":
Этот элемент задается конструкцией вида:
name="{имя}"
namespace="{пространство имен}">
Использование элементов
xsl:attribute
и xsl:element
во многом аналогично. Обязательный атрибут name указывает имя, а атрибут namespace
— URI пространства имен создаваемого атрибута, причем процесс вычисления расширенного имени атрибута практически идентичен этому в процедуре вычисления имени элемента, который был приведен при разборе xsl:element
.
Показаний к применению
xsl:attribute
несколько больше, чем для xsl:element
. В частности, xsl:attribute
следует использовать, если:
□ требуется создать атрибут с не известным заранее именем или пространством имен;
□ требуется создать атрибут в пространстве имен, которое является для процессора значащим (например, в пространстве имен XSLT);
□ требуется создать атрибут, вычисление значения которого не может быть реализовано одним или несколькими XPath-выражениями (например, условный вывод атрибута).
Приведем некоторые примеры.
Покажем, как преобразовать структуру вида
в элемент
Для достижения цели воспользуемся следующим преобразованием.
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
Элемент
xsl:attribute
не может использоваться где угодно: узлы атрибутов должны создаваться только как дочерние узлы узлов элементов. Более того, узлы атрибутов должны создаваться до создания дочерних узлов других типов — текста, элементов и так далее. Таким образом, xsl:attribute
может быть использован в содержимом любого из следующих родителей:
□ литерального элемента результата;
□ элемента
xsl:element
;
□ элемента
xsl:copy
в случае, если текущий, копируемый узел является элементом;
□ элемента
xsl:attribute-set
в случае определения именованного набора атрибутов.
При этом, как было показано в предыдущем примере,
xsl:attribute
не обязан использоваться только в качестве их непосредственного дочернего элемента. Главное, чтобы атрибуты создавались в элементах и только в элементах.
Элемент
xsl:attribute
также не может использоваться для генерации объявлений пространств имен. В соответствии с технической рекомендацией XSLT, xsl:attribute
не может создавать атрибуты, имена которых имеют префикс xmlns
.
Если атрибут создается в элементе, который уже имеет атрибут с таким же именем, старый атрибут будет переопределен новым значением.
Рассмотрим пример.
<а href="http://www.aaa.com">
http://www.bbb.com
Поскольку атрибут может содержать только текст, результатом выполнения содержимого
xsl:attribute
тоже должны быть только текстовые узлы. Процессор в лучшем случае проигнорирует нетекстовые узлы, в худшем выведет сообщение об ошибке, прервав дальнейшую обработку, так что следует очень внимательно относиться к содержимому xsl:attribute
.
Текстовое значение атрибута может задаваться не только символьными данными, Оно может генерироваться также элементами XSLT, такими, как, например,
xsl:text
и xsl:value-of
. То есть вполне корректным будет следующее определение:
http://
.com
В том случае, если текстовое значение атрибута содержит символы перевода строки, при генерации атрибута они будут заменены сущностями, то есть определение
а¶
b
создаст атрибут с именем "
href
" и значением "a
b
":
<а href="a
b"/>
Техническая рекомендация объясняет такую ситуацию следующим образом: в соответствии со стандартом языка XML, символы перевода строки должны нормализоваться в значениях атрибутов пробелами, сущности же нормализовать не нужно. Но если бы символ перевода строки нормализовался в XSLT при выводе пробелом, то определения
a□b
и
a¶
b
были бы эквивалентны, что не отражает реального положения вещей. Для того чтобы исправить эту несуразицу, символ перевода строки при выводе в атрибуте нормализуется в XSLT символьной сущностью (
или
).
Подводя итог, перечислим в краткой форме основные особенности обращения с
xsl:attribute
.
□ Атрибуты могут создаваться только в узлах элементов. Если атрибут создается в узле, который не является узлом элемента, процессор может либо выдать ошибку, либо проигнорировать создаваемый атрибут.
□ Атрибуты могут содержать только текстовые узлы. Процессор может либо выдать ошибку, либо проигнорировать нетекстовые узлы.
□ Узлы атрибутов должны быть первыми узлами, которые создаются в элементах. XSLT не разрешает создавать атрибуты после того, как в элемент включены дочерние узлы других типов.
□ В случае, когда документ преобразуется в другой XML-документ, символы перевода строки в элементе заменяются символьными сущностями.
Синтаксис элемента определяется следующей конструкцией:
name="имя"
use-attribute-sets="имена">
Для того чтобы упростить создание в элементах целых наборов атрибутов, можно заранее определить их в элементе
xsl:attribute-set
. Обязательный атрибут name
задает имя набора атрибутов. Элемент xsl:attribute-set
содержит последовательность, состоящую из нуля или более элементов xsl:attribute
.
Именованные наборы атрибутов можно использовать, указывая их имена в значении атрибута
use-attribute-sets
, который может присутствовать в элементах xsl:element
, xsl:copy
и xsl:attribute-set
, а также в литеральных результирующих элементах. В атрибуте use-attribute-sets
через пробел перечисляются имена наборов атрибутов, которые должны быть использованы в данном элементе.
Включение набора атрибутов в элемент равносильно простому копированию элементов
xsl:attribute
, определенных в соответствующих элементах xsl:attribute-set
.
Предположим, что во входящем документе нам нужно вывести структуру, состоящую из элементов с именем
element
, атрибут name
которых равен имени, атрибут attr-count
— количеству атрибутов, а атрибут node-count
— количеству дочерних узлов соответствующего элемента.
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
use-attribute-sets="elements attrs">
В этом преобразовании определение элемента
use-attribute-sets="elements attrs">
равносильно определению
Как уже было сказано, элемент
xsl:attribute-set
может также использовать другие наборы атрибутов при помощи use-attribute-sets
. Например, в предыдущем преобразовании набор атрибутов elements
мог быть определен как:
use-attribute-sets="attrs">
Тогда для достижения того же результата элемент с именем
element
мог быть создан с использованием только одного набора атрибутов:
use-attribute-sets="elements">
Именованный набор атрибутов не может прямо или косвенно (посредством других наборов атрибутов) использовать в значении
use-attribute-sets
себя самого. Такая ситуация породила бы бесконечный цикл. Вообще, не рекомендуется выстраивать сложную иерархию именованных наборов атрибутов, поскольку это может сильно усложнить обработку и снизить эффективность преобразования, хотя, естественно, все зависит от конкретного случая.
Мы упомянули о том, что именованные наборы атрибутов используются в элементах посредством атрибута
xsl:use-attribute-sets
. Разберем более детально, где этот атрибут может применяться, и какие функции он при этом выполняет. Для удобства эти данные сведены в табл. 7.1.
Таблица 7.1. Использование атрибута
xsl:use-attribute-sets
Родительский элемент | Особенности использования |
---|---|
|
Включает в определяемый набор атрибутов атрибуты из перечисленных наборов |
|
Включает в создаваемый элемент атрибуты из перечисленных наборов. Включение эквивалентно текстовому включению — значения атрибутов вычисляются в контексте создающего элемента
|
|
Включает в копируемый элемент атрибуты из перечисленных наборов. Принцип действия— как в случае с . Копируемый узел должен быть элементом |
Литеральный результирующий элемент | Принцип действия такой же, как и в случае с . В случае совпадения имен, значения атрибутов из набора будут переопределять значения атрибутов самого элемента. При использовании в литеральном элементе, атрибут должен быть обязательным образом объявлен принадлежащим пространству имен XSLT. Как правило, это делается указанием префикса
|
Шаблон преобразования может содержать текстовые узлы, которые при выполнении шаблона после обработки пробельных символов будут попросту скопированы в результирующее дерево. Таким образом, для того, чтобы вывести в выходящий документ некоторый текст, можно просто включить его в шаблон преобразования.
Рассмотрим пример.
No!
The answer was " ".
The answer was "No!".
Текстовые узлы могут также быть созданы элементами
xsl:text
и xsl:value-of
. Элемент xsl:text
используется для создания текстовых узлов, содержащих пробельные и специальные символы, в то время как элемент xsl:value-of
выводит в выходящее дерево строковый результат вычисления выражений.
Синтаксис данного элемента представлен ниже:
disable-output-escaping="yes" | "no">
Элемент
xsl:text
служит для того, чтобы создавать в выходящем документе текстовые узлы. При этом xsl:text
имеет следующие особенности.
□ Преобразования будут сохранять пробельные символы, находящиеся в элементе
xsl:text
. То есть, для того чтобы вывести в выходящий документ пробельный символ, например такой, как символ перевода строки, достаточно написать
□ Элемент
xsl:text
имеет атрибут disable-output-escaping
, который позволяет избежать замены в выходящем документе специальных символов на символьные или встроенные сущности. Например, для того, чтобы вывести символ "<
" можно указать в преобразовании
<
В остальных случаях символьные данные, включенные в элемент
xsl:text
, ведут себя так же, как и вне xsl:text
.
Этот элемент является одним из наиболее часто используемых в XSLT. Он служит для вычисления значений выражений.
Синтаксическая конструкция элемента следующая:
select="выражение"
disable-output-escaping="yes" | "no"/>
В обязательном атрибуте
select
этого элемента задается выражение, которое вычисляется процессором, затем преобразовывается в строку и выводится в результирующем дереве в виде текстового узла. Процессор не станет создавать текстовый узел, если результатом вычисления выражения была пустая строка. В целях оптимизации дерева, соседствующие текстовые узлы будут объединены в один.
Элемент
xsl:value-of
очень похож на элемент xsl:copy-of
, только в отличие от последнего он сначала преобразовывает вычисленное выражение к строковому виду, а уж затем выводит его в выходящий документ. Иными словами, выражение
равносильно
Соответственно, преобразование различных типов данных в строковый тип производится точно так же, как если бы мы использовали для этой цели функцию
string
.
Для составления таблицы умножения можно воспользоваться следующим преобразованием.
1
2
3
4
5
6
7
8
9
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
1 2 3 4 5 6 7 8 9
2 4 6 8 10 12 14 16 18
3 6 9 12 15 18 21 24 27
4 8 12 16 20 24 28 32 36
5 10 15 20 25 30 35 40 45
6 12 18 24 30 36 42 48 54
7 14 21 28 35 42 49 56 63
8 16 24 32 40 48 56 64 72
9 18 27 36 45 54 63 72 81
В данном случае элемент
xsl:value-of
используется для вычисления произведения переменных a
и b
. Численный результат преобразуется в строку и выводится в выходящий документ в виде текста.
Равно, как и
xsl:text
, элемент xsl:value-of
может иметь атрибут disable-output-escaping
, полезный для вывода специальных символов, которые в противном случае были бы заменены сущностями.
Результатом выполнения элемента
будет текстовый узел
Divide & impera
Чтобы придать амперсанту более привычный вид, мы можем использовать атрибут
disable-output-escaping
:
select="concat('Divide ', '&', ' impera')"
disable-output-escaping="yes"/>
Результатом выполнения этого шаблона уже будет текст:
Divide & impera
Этот элемент задается конструкцией вида:
Элемент
xsl:comment
создает в результирующем дереве узел комментария. Текстом комментария становится результат выполнения шаблона, который содержится в элементе xsl:comment
.
Точно так же как и в случае с
xsl:processing-instruction
, результат выполнения шаблона должен содержать только текстовые узлы. Узлы других типов будут либо проигнорированы, либо вызовут ошибку.
В соответствии с синтаксисом XML, комментарий в XML не может содержать двух знаков "
-
" последовательно ("--
") и оканчиваться на "-
". Поэтому наличие таких последовательностей символов в тексте комментария будет являться в XSLT ошибкой. Для того чтобы избежать некорректного синтаксиса, процессор может разделять два последовательных минуса пробелом (заменять "--
" на "- -
") или добавлять пробел после завершающего минуса комментария.
Элемент:
| Please remove this later
+
создаст комментарий:
Синтаксис элемента представлен ниже:
name="{имя}">
Элемент
xsl:processing-instruction
создает в результирующем дереве узел инструкции по обработке. Обязательный атрибут name определяет имя целевого приложения, которому будет адресована инструкция по обработке. В этом атрибуте может быть указан шаблон значения атрибута.
Элемент:
links="follow" session-timeout="7200000"
создаст в выходящем документе инструкцию по обработке вида:
Содержимым создаваемой инструкции по обработке является результат выполнения шаблона, содержащегося внутри элемента
xsl:processing- instruction
. Этот результат должен содержать только текстовые узлы, в противном случае процессор может либо выдать ошибку, либо проигнорировать нетекстовые узлы вместе с их содержимым.
Инструкция по обработке не может содержать последовательности символов "
?>
", поскольку это было бы некорректно с точки зрения синтаксиса XML.
В случае, если результат выполнения шаблона содержит такую комбинацию, процессор может либо выдать ошибку, либо разделить символы "
?
" и ">
" пробелом:"? >
".
Имя инструкции по обработке, должно быть корректным XML-именем (но не равным при этом "
xml
" в любом регистре символов). Например, следующее определение будет совершенно корректным:
logout _
В результате получится следующая инструкция:
Для того чтобы создать в выходящем XML-документе инструкцию
xml-stylesheet
, которая используется для связывания документов со стилями и преобразованиями, можно воспользоваться следующим определением:
href="style.xsl" type="text/xsl"
Результирующий документ будет содержать инструкцию по обработке в виде:
Элемент
xsl:processing-instruction
не может создать декларацию XML, несмотря на то, что с точки зрения синтаксиса (но не семантики) она имеет форму инструкции по обработке. Для вывода XML-декларации следует использовать элемент xsl:output
.
Преобразование может включать в себя не только создание новых, но и копирование существующих узлов. Для этого можно использовать элементы
xsl:copy
и xsl:copy-of
, использование которых будет подробно разобрано ниже.
Ниже представлена синтаксическая конструкция этого элемента:
use-attribute-sets = "наборы атрибутов">
Элемент
xsl:copy
создает копию текущего узла вне зависимости от его типа. Вместе с текущим узлом в выходящее дерево копируются только узлы пространств имен, ассоциированные с ним. Дочерние узлы и узлы атрибутов в выходящий документ не копируются.
Если
xsl:copy
используется для копирования корневого узла или узда элемента, в выходящем документе процессор создает дочерний фрагмент дерева, являющийся результатом выполнения шаблона, содержащегося в xsl:copy
.
Предположим, что в каждый элемент преобразовываемого документа нам нужно добавить атрибут
element-count
со значением, равным количеству его дочерних элементов, а все остальные узлы оставить, как есть.
<а> text
text
text
text
Если
xsl:copy
используется для создания в выходящем документе копии узла элемента, в него при помощи атрибута use-attribute-sets
могут быть также включены именованные наборы атрибутов (см. раздел "Именованные наборы атрибутов" данной главы).
Предыдущее преобразование может быть переписано в виде
Результат преобразования будет абсолютно идентичен выходящему документу, полученному в предыдущем примере.
Синтаксис элемента несложен:
select="выражение"/>
Использование элемента
xsl:copy-of
полностью аналогично использованию элемента xsl:value
-of за тем исключением, что xsl:copy-of
при выводе значения выражения преобразует его к строке не во всех случаях. Поведение xsl:copy-of
зависит от того, какой тип данных возвращает выражение.
□ Если результат вычисления имеет булевый, числовой или строковый тип, то
xsl:copy-of
выводит его в виде текстового узла. В этом случае поведение xsl:copy-of
абсолютно не отличается от поведения элемента xsl:value-of
.
□ Если результатом вычисления выражения является множество узлов (node-set), то
xsl:copy-of
копирует в выходящий документ все узлы в порядке просмотра документа вместе с их потомками.
□ Если результатом вычисления является результирующий фрагмент дерева, то он копируется в выходящий документ в неизмененном виде.
Рассмотрим пример.
false
text
3.14
- 10
- 20
- 30
text
text
text
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
Value-of boolean:
Copy-of boolean:
Value-of string:
Copy-of string:
Value-of number:
Copy-of number:
Value-of node-set:
Copy-of node-set:
Value-of tree:
Copy-of tree:
Value-of boolean:false
Copy-of boolean:false
Value-of string:text
Copy-of string:text
Value-of number:3.14
Copy-of number:3.14
Value-of node-set:10
Copy-of node-set:- 10
- 20
- 30
Value-of tree:
text
text
Copy-of tree:
text
text
В XSLT имеются две инструкции, которые поддерживают условную обработку —
xsl:if
и xsl:choose
. Инструкция xsl:if
позволяет создавать простые условия типа "если-то", в то время как xsl:choose
создает более сложную конструкцию для выбора одной из нескольких имеющихся возможностей в зависимости от выполнения тех или иных условий.
Синтаксис элемента следующий:
test="выражение">
Элемент
xsl:if
является простейшим условным оператором в XSLT. Выражение, содержащееся в обязательном атрибуте test
, вычисляется и приводится к булевому типу. В том и только том случае, если выражение имеет значение true
, процессор выполняет шаблон, содержащийся в xsl:if
.
Вследствие того, что атрибуты в XML не могут содержать некоторые специальные символы (такие как "
<
" и "&
"), их необходимо заменять символьными сущностями. В особенности это касается сравнения чисел типа "меньше"; объявление вида
будет с точки зрения синтаксиса XML некорректным. Вместо него следует использовать эквивалентное объявление
Следует заметить, что символ "больше" ("
>
") заменять сущностью необязательно. Однако из соображений единообразия принято заменять и его.
Предположим, мы преобразовываем список названий
- Alpha
- Bravo
- Charlie
во фрагмент HTML-кода, в котором каждый элемент
item
должен быть преобразован в соответствующий элемент option
, а значение, выбранное во входящем документе атрибутом active
элемента list
, должно быть помечено булевым атрибутом selected
.
selected
Результат:
В данном преобразовании использовался метод вывода "
html
". Подробнее о методах вывода выходящего документа см. раздел "Контроль вывода документа" 8 главы.
К сожалению, элемент
xsl:if
в XSLT не может реализовать конструкцию if-then-else (англ. если-то-иначе). Условные выражения такого вида реализуются при помощи элементов xsl:choose
, xsl:when
и xsl:otherwise
.
Ниже даны синтаксические конструкции этих элементов:
test="выражение">
Элемент
xsl:choose
содержит один или несколько элементов xsl:when
и необязательный элемент xsl:otherwise
. При обработке xsl:choose
процессор поочередно вычисляет выражения, содержащиеся в атрибутах test
элементов xsl:when
, приводит их к булевому типу и выполняет содержимое первого (и только первого) элемента, тестовое выражение которого будет равно true
. В случае если ни одно из тестовых выражений не обратилось в "истину" и в xsl:choose
присутствует xsl:otherwise
, процессор выполнит содержимое этого элемента.
Элементы
xsl:choose
, xsl:when
и xsl:otherwise
можно совместно использовать для получения конструкции типа if-then-else. Условие вида "если выражение A
истинно, то выполнить действие B
иначе выполнить действие C
", которое в других языках программирования может быть записано, к примеру, как
если
верно условиеА
то
выполнить шаблонB
иначе
выполнить шаблонC
в XSLT может быть определено следующим образом:
шаблонB
шаблонC
Вместе с тем, условие вида "если — то — иначе" это не все, на что способен элемент
xsl:choose
. Возможность указывать несколько элементов xsl:when
позволяет записывать более сложные условия выбора вида:
если
верно условие1
то
выполнить шаблон1
иначе если
верно условие2
то
выполнить шаблон2
...
иначе если
верно условиеN
то
выполнить шаблонN
иначе
выполнить шаблонМ
Такой множественный условный переход совершенно прозрачно оформляется в виде следующей
xsl:choose
-конструкции:
шаблон1
шаблон2
шаблонN
шаблонМ
Конструкция этого элемента такова:
select="выражение">
Элемент
xsl:for-each
используется для создания в выходящем документе повторяемых частей структуры. Обязательный атрибут select
указывает выражение, результатом вычисления которого должно быть множество узлов. Шаблон, содержащийся в xsl:for-each
, будет выполнен процессором для каждого узла этого множества.
Мы можем использовать
xsl:for-each
для того, чтобы создать список гипертекстовых ссылок для документа вида.
I'm just a simple page...
Please visit this link.
Or this one.
Or visit this site.
Or click here.
Будем считать, что в этом документе элементы гипертекстовых ссылок а являются потомками элемента
body
, который находится в элементе html
.
http://www.aaa.com
http://www.bbb.com
http://www.ccc.com
http://www.ddd.com
Элемент
xsl:for-each
изменяет контекст преобразования. Множество узлов, возвращаемое выражением в атрибуте select
, становится текущим множеством узлов, а узел, шаблон для которого выполняется в данный момент, становится текущим узлом.
Как мы знаем, множества узлов в XSLT не имеют внутреннего порядка. Однако, обработка узлов в
xsl:for-each
будет происходить в так называемом порядке просмотра документа, который зависит от того, какое выражение использовалось для вычисления обрабатываемого множества. Порядок обработки множества узлов в xsl:for-each
может быть также изменен элементами xsl:sort
, которые могут присутствовать в xsl:for-each
. Элемент xsl:sort
задает сортировку обрабатываемого множества узлов, изменяя, таким образом, порядок просмотра, что часто бывает очень полезно.