xsl:element¶
XSLT предоставляет возможность создавать узлы элементов при помощи элемента xsl:element.
Синтаксис¶
1 2 3 4 5 6 7 | |
Атрибуты:
name- обязательный атрибут, указывает имя создаваемого элемента. Этот атрибут может содержать шаблон значения, а значит, имя элемента может быть вычислено во время выполнения.
namespace- необязательный атрибут, указывает URI пространства имен создаваемого элемента. Точно так же, как и
name, этот атрибут может содержать шаблон значения, что позволяет вычислять пространство имен создаваемого элемента при помощи выражений. use-attribute-sets- необязательный атрибут, перечисляет имена наборов атрибутов, которые должны быть включены в создаваемый элемент.
Содержимым xsl:element является шаблон, который выполняется процессором и затем включается в создаваемый элемент.
Описание и примеры¶
Пример¶
Предположим, мы хотим поменять имя каждого элемента на значение его первого атрибута и наоборот.
Листинг 7.1. Входящий документ
1 | |
Листинг 7.2. Шаблон, заменяющий имя элемента значением атрибута
1 2 3 4 5 6 7 | |
Листинг 7.3. Выходящий документ
1 | |
В этом примере код <xsl:element name="{@*}">...</xsl:element> создает элемент, именем которого становится значение выражения @*, указанного в виде шаблона значения атрибута name. Это выражение выбирает множество, состоящее из узлов атрибутов текущего элемента, а если привести его к строке, в результате получится текстовое значение первого атрибута элемента.
Подобным образом выбирается имя атрибута создаваемого элемента и его значение.
Вычисленное значение атрибута name может задавать и расширенное имя элемента, то есть иметь форму префикс:имя. В этом случае элемент будет создаваться в том пространстве имен, которое соответствует указанному префиксу, например
1 | |
создаст элемент вида
1 2 3 | |
Заметим, что элемент вида
1 | |
даст тот же результат.
Другим способом указания пространства имен при использовании элемента xsl:element является использование атрибута namespace. Например, для предыдущего случая мы могли бы записать
1 2 3 4 | |
и получить в итоге
1 | |
что эквивалентно результату предыдущего примера, хоть и различается внешне.
Атрибут namespace тоже может быть сконструирован на этапе выполнения, например:
1 2 3 4 | |
что также даст элемент template, принадлежащий пространству имен XSLT.
Для того чтобы разобраться в приоритетах атрибутов name и namespace на определение пространства имен, приведем несколько правил, которые пояснят этот процесс.
- Если в элементе
xsl:elementопределен атрибутnamespace, то создаваемый элемент будет принадлежать пространству имен с URI, который будет значением этого атрибута. Если значением атрибутаnamespaceбудет пустая строка, создаваемый элемент будет принадлежать нулевому пространству имен. Как правило, процессоры используют префикс, указанный в имени атрибутом name, но, вместе с тем, они не обязаны так делать. Поэтому в общем случае следует ожидать, что префикс может быть любым. - Если в элементе
xsl:elementне определен атрибутnamespace, но имя, заданное в атрибутеnameимеет префикс, то создаваемый элемент будет принадлежать соответствующему этому префиксу пространству имен. Однако и в этом случае не гарантируется, что префикс создаваемого элемента будет таким, каким он был задан в атрибутеname. - В случае, если в элементе
xsl:elementне определен атрибутnamespaceи имя, заданное в атрибутеnameне имеет префикса, создаваемый элемент будет принадлежать пространству имен, которое действует для создающего элементаxsl:elementпо умолчанию.
Повторим еще раз, что во всех трех случаях сказать что-либо достоверно о префиксе создаваемого элемента нельзя — префикс с точки зрения пространств имен не является значащей частью имени элемента. Вместе с тем, на практике процессоры, как правило, используют префикс, указанный в атрибуте name, или не используют префикс вообще, если префикс в name указан не был.
Приведем несколько примеров.
Для начала покажем, что, согласно первому правилу, атрибут namespace имеет наивысший приоритет при определении пространства имен выходящего элемента. Рассмотрим следующее преобразование.
Листинг 7.4.
1 2 3 4 5 6 7 8 9 10 11 | |
В выделенном элементе xsl:element пространство имен создаваемого элемента указано вроде бы два раза: в виде значения атрибута namespace и в виде префикса имени ("xsl"). Результат будет выглядеть следующим образом:
1 | |
Процессор использовал пространство имен, указанное в атрибуте namespace, локальную часть имени, заданного атрибутом name ("html"), а также префикс (только префикс, но не связанное с ним пространство имен) этого имени ("xsl").
В свою очередь конструкция вида
1 | |
создаст элемент
1 | |
что на самом деле эквивалентно просто <html/>.
Таким образом, атрибут namespace наиболее приоритетен для определения пространства имен создаваемого элемента. Обратимся теперь к случаю, когда этот атрибут опущен в xsl:element. Объявление вида
1 | |
создаст элемент
1 2 3 | |
Как видим, отсутствие namespace и namespace="" — не одно и то же.
Рассмотрим теперь случай, когда нет ни атрибута namespace, ни префикса в name:
1 2 3 4 5 6 7 8 | |
Результатом этого преобразования будет документ, состоящий из одного пустого элемента html:
1 | |
Мы специально привели все преобразование целиком, чтобы показать, что выходящий элемент будет принадлежать нулевому пространству имен тогда и только тогда, когда для него не было объявлено пространства имен по умолчанию. Попробуем посмотреть, что получится, если пространство имен по умолчанию будет объявлено:
1 2 3 4 5 6 7 8 9 10 11 | |
Результатом в этот раз будет элемент с локальной частью имени "html", принадлежащий пространству имен с URI "http://www.w3.org/1999/xhtml":
1 | |
Пример для XSLT 2.0¶
Мы переходим к примеру, в котором используется поддержка схем в XSLT 2.0. Атрибут validation элемента <xsl:element> поможет убедиться в том, что создаваемый элемент действителен в соответствии со схемой заказа. Мы начнем с файла XML, содержимое которого по формату сходно с данными заказов:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | |
Элемент <xsl:element> будет использоваться для создания нового заказа на основании данных из документа. Необходимо также сгенерировать элемент <date>, являющийся первым дочерним элементом <purchase-order>. Таблица стилей выглядит так:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 | |
Таблица стилей использует элементы <xsl:element> и <xsl:attribute> для построения заказа «с нуля». Атрибут validation="strict" означает, что сгенерированный элемент <purchase-order> должен представлять действительный заказ при проверке по схеме po.xsd. Если таблица стилей попытается добавить в сгенерированный элемент <purchase-order> что-либо, нарушающее схему заказа, ядро XSLT инициирует исключение и прерывает работу. Таблица стилей генерирует следующий код XML:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | |
Сгенерированный документ использует пространство имен по умолчанию http://www.oreilly.com/xslt. Это пространство имен связано с импортированной схемой; тот факт, что оно объявляется как пространство имен по умолчанию для таблицы стилей, означает, что оно будет скопировано в выходной элемент. Обратите также внимание на использование в таблице стилей атрибута exclude-result-prefixes, из-за которого префиксы po и xs не попадают в сгенерированный документ. Как и следовало ожидать, пространством имен по умолчанию для сгенерированного заказа является пространство имен http://www.oreilly.com/xslt.
При создании элемента <date> используется функция current-date(). Чтобы увидеть, что произойдет в случае неудачной проверки, удалите элемент <date>. Появится следующее сообщение об ошибке:
1 2 3 4 5 | |
В этом случае элемент <purchase-order> не генерируется, потому что без находящегося в положенном месте элемента <date> он недействителен.
См. также¶
xsl:attribute— создание атрибутов элемента.local-name()— возвращает локальную часть имени первого в порядке просмотра документа узла множества.name()— возвращает расширенное имя.
Ссылки¶
xsl:elementMDN (рус.)xsl:elementMSDN (en)