— создание текстового узла по результатам вычисления выражения;
□
xsl:comment
— создание узла комментария;
□
xsl:processing-instruction
—
создание узла инструкции по обработке;
□
xsl:copy
— копирование текущего узла вместе с его узлами пространств имен;
□ x
sl:copy-of
— копирование результата вычисления выражения;
□
xsl:if
— условная обработка;
□
xsl:choose
,
xsl:when
и
xsl:otherwise
— выбор одной из нескольких альтернатив согласно некоторым условиям;
□
xsl:for-each
— итеративная обработка множества узлов.
Создание узлов элементов
В четвертой главе мы уже разобрали один из способов создания в выходящем документе узлов элементов, а именно — использование литеральных элементов результата, которые в неизменном виде копируются процессором в выходящее дерево. Этот способ прост, понятен и удобен, однако есть две основные проблемы, которые он не может решить.
□ Что, если в выходящем документе требуется создать элемент с заранее неизвестным (например, вычисляемым во время выполнения) именем?
□ Как создать элемент, принадлежащий пространству имен, известному обрабатывающему процессору?
Поясним на примерах суть и той и другой проблемы.
Представим себе входящий документ вида
<element name="a">
<element name="b"/>
</element>
который нужно преобразовать во что-нибудь наподобие
<а>
<b/>
</а>
Совершенно очевидно, что литеральными элементами тут не обойдешься — мы не знаем заранее имена элементов выходящего документа, ибо они определяются значениями атрибутов входящего.
Представим теперь, что нам в XSLT-преобразовании необходимо сгенерировать другое XSLT-преобразование. Скажем из элемента вида
<remove element="a"/>
нужно получить шаблон
<xsl:template match="a"/>
Беда в том, что литеральные элементы не могут быть использованы для создания, скажем, элемента
xsl:template
по той причине, что любой элемент с локальной частью имени
template
, принадлежащий пространству имен XSLT будет рассматриваться процессором, как элемент самого преобразования. Очевидно, что
<xsl:template match="remove">
<xsl:template match="{@element}"/>
</xsl:template>
будет
некорректным определением. He поможет и смена префикса, ведь принадлежность пространству имен определяется не им.
Для того чтобы решить эти проблемы (главным образом, первую), XSLT предоставляет возможность создавать узлы элементов при помощи элемента
xsl:element
.
Элемент xsl:element
Синтаксическая конструкция этого элемента задается следующим образом:
<xsl:element
name="{имя}"
namespace="{пространство имен}
"use-attribute-sets="имена">
<!-- Содержимое: шаблон -->
</xsl:element>
Здесь обязательный атрибут
name
указывает имя создаваемого элемента. Этот атрибут может содержать шаблон значения, а значит, имя элемента может быть вычислено во время выполнения.
Атрибут
namespace
указывает URI пространства имен создаваемого элемента. Точно так же, как и name, этот атрибут может содержать шаблон значения, что позволяет вычислять пространство имен создаваемого элемента при помощи выражений.
Атрибут
use-attribute-sets
перечисляет имена наборов атрибутов, которые должны быть включены в создаваемый элемент.
Содержимым
xsl:element
является шаблон, который выполняется процессором и затем включается в создаваемый элемент.
Пример
Предположим, мы хотим поменять имя каждого элемента на значение его первого атрибута и наоборот.
Листинг 7.1. Входящий документ
<fire on="babylon"/>
Листинг 7.2. Шаблон, заменяющий имя элемента значением атрибута
<xsl:template match="*">
<xsl:element name="{@*}">
<xsl:attribute name="{name(@*)}">
<xsl:value-of select="name"/>
</xsl:attribute>
</xsl:element>
</xsl:template>
Листинг 7.3. Выходящий документ
<babylon on="fire"/>
В этом примере код
<xsl:element name="{@*}">...</xsl:element>
создает элемент, именем которого становится значение выражения
@*
, указанного в виде шаблона значения атрибута
name
. Это выражение выбирает множество, состоящее из узлов атрибутов текущего элемента, а если привести его к строке, в результате получится текстовое значение первого атрибута элемента.