пространству имен определяется не им.
Для того чтобы решить эти проблемы (главным образом, первую), XSLT предоставляет возможность создавать узлы элементов при помощи элемента xsl:element
.
Элемент
Синтаксическая конструкция этого элемента задается следующим образом:
<xsl:element
name='{
namespace='{
'use-attribute-sets='
<!-- Содержимое: шаблон -->
</xsl:element>
Здесь обязательный атрибут name
указывает имя создаваемого элемента. Этот атрибут может содержать шаблон значения, а значит, имя элемента может быть вычислено во время выполнения.
Атрибут namespace
указывает URI пространства имен создаваемого элемента. Точно так же, как и name, этот атрибут может содержать шаблон значения, что позволяет вычислять пространство имен создаваемого элемента при помощи выражений.
Атрибут use-attribute-sets
перечисляет имена наборов атрибутов, которые должны быть включены в создаваемый элемент.
Содержимым xsl:element
является шаблон, который выполняется процессором и затем включается в создаваемый элемент.
Предположим, мы хотим поменять имя каждого элемента на значение его первого атрибута и наоборот.
<fire on='babylon'/>
<xsl:template match='*'>
<xsl:element name='{@*}'>
<xsl:attribute name='{name(@*)}'>
<xsl:value-of select='name()'/>
</xsl:attribute>
</xsl:element>
</xsl:template>
<babylon on='fire'/>
В этом примере код <xsl:element name='{@*}'>...</xsl:element>
создает элемент, именем которого становится значение выражения @*
, указанного в виде шаблона значения атрибута name
. Это выражение выбирает множество, состоящее из узлов атрибутов текущего элемента, а если привести его к строке, в результате получится текстовое значение первого атрибута элемента.
Подобным образом выбирается имя атрибута создаваемого элемента и его значение.
Вычисленное значение атрибута name
может задавать и расширенное имя элемента, то есть иметь форму
. В этом случае элемент будет создаваться в том пространстве имен, которое соответствует указанному префиксу, например
<xsl:element name='xsl:template'/>
создаст элемент вида
<xsl:template xmlns:xsl='http://www.w3.org/1999/XSL/Transform'/>
Заметим, что элемент вида
<xsl:element name='{concat{'xsl',':','template')}'/>
даст тот же результат.
Другим способом указания пространства имен при использовании элемента xsl:element
является использование атрибута namespace
. Например, для предыдущего случая мы могли бы записать
<xsl:element
name='template'
namespace='http://www.w3.org/1999/XSL/Transform'/>
и получить в итоге
<template xmlns='http://www.w3.org/1999/XSL/Transform'/>
что эквивалентно результату предыдущего примера, хоть и различается внешне.
Атрибут namespace
тоже может быть сконструирован на этапе выполнения, например:
<xsl:element
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
имеет наивысший приоритет при определении пространства имен выходящего элемента. Рассмотрим следующее преобразование.