Алексей Валиков - Технология XSLT
<xsl:attribute name="href">
<xsl:text>http://</xsl:text>
<xsl:value-of select="concat('www', '.', 'bbb')"/>
<xsl:text>.com</xsl:text>
</xsl:attribute>
В том случае, если текстовое значение атрибута содержит символы перевода строки, при генерации атрибута они будут заменены сущностями, то есть определение
<xsl:attribute name="href">а¶
b</xsl:attribute>
создаст атрибут с именем "href" и значением "a
b":
<а href="a
b"/>
Техническая рекомендация объясняет такую ситуацию следующим образом: в соответствии со стандартом языка XML, символы перевода строки должны нормализоваться в значениях атрибутов пробелами, сущности же нормализовать не нужно. Но если бы символ перевода строки нормализовался в XSLT при выводе пробелом, то определения
<xsl:attribute name="href">a□b</xsl:attribute>
и
<xsl:attribute name="href">a¶
b</xsl:attribute>
были бы эквивалентны, что не отражает реального положения вещей. Для того чтобы исправить эту несуразицу, символ перевода строки при выводе в атрибуте нормализуется в XSLT символьной сущностью (
 или ).
Подводя итог, перечислим в краткой форме основные особенности обращения с xsl:attribute.
□ Атрибуты могут создаваться только в узлах элементов. Если атрибут создается в узле, который не является узлом элемента, процессор может либо выдать ошибку, либо проигнорировать создаваемый атрибут.
□ Атрибуты могут содержать только текстовые узлы. Процессор может либо выдать ошибку, либо проигнорировать нетекстовые узлы.
□ Узлы атрибутов должны быть первыми узлами, которые создаются в элементах. XSLT не разрешает создавать атрибуты после того, как в элемент включены дочерние узлы других типов.
□ В случае, когда документ преобразуется в другой XML-документ, символы перевода строки в элементе заменяются символьными сущностями.
Именованные наборы атрибутов
Элемент xsl:attribute-set
Синтаксис элемента определяется следующей конструкцией:
<xsl:attribute-set
name="имя"
use-attribute-sets="имена">
<!-- Содержимое: несколько элементов xsl:attribute -->
</xsl:attribute-set>
Для того чтобы упростить создание в элементах целых наборов атрибутов, можно заранее определить их в элементе 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 — количеству дочерних узлов соответствующего элемента.
Листинг 7.8. Входящий документ<a b="1" c="2">
<d e="3" f="4" g="5"/>
</a>
Листинг 7.9. Преобразование<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:attribute-set name="attrs">
<xsl:attribute name="attr-count">
<xsl:value-of select="count(@*)"/>
</xsl:attribute>
</xsl:attribute-set>
<xsl:attribute-set name="elements">
<xsl:attribute name="name">
<xsl:value-of select="name()"/>
</xsl:attribute>
<xsl:attribute name="node-count">
<xsl:value-of select="count(*)"/>
</xsl:attribute>
</xsl:attribute-set>
<xsl:template match="*">
<xsl:element name="element"
use-attribute-sets="elements attrs">
<xsl:apply-templates select="*"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
Листинг 7.10. Выходящий документ<?xml version="1.0" encoding="utf-8"?>
<element name="a" node-count="1" attr-count="2">
<element name="d" node-count="0" attr-count="3"/>
</element>
В этом преобразовании определение элемента
<xsl:element name="element"
use-attribute-sets="elements attrs">
<xsl:apply-templates select="*"/>
</xsl:element>
равносильно определению
<xsl:element name="element">
<xsl:attribute name="name">
<xsl:value-of select="name()"/>
</xsl:attribute>
<xsl:attribute name="node-count">
<xsl:value-of select="count(*)"/>
</xsl:attribute>
<xsl:attribute name="attr-count">
<xsl:value-of select="count(@*)"/>
</xsl:attribute>
<xsl:apply-templates select="*"/>
</xsl:element>
Как уже было сказано, элемент xsl:attribute-set может также использовать другие наборы атрибутов при помощи use-attribute-sets. Например, в предыдущем преобразовании набор атрибутов elements мог быть определен как:
<xsl:attribute-set name="elements"
use-attribute-sets="attrs">
<xsl:attribute name="name">
<xsl:value-of select="name()"/>
</xsl:attribute>
<xsl:attribute name="node-count">
<xsl:value-of select="count(*)"/>
</xsl:attribute>
</xsl:attribute-set>
Тогда для достижения того же результата элемент с именем element мог быть создан с использованием только одного набора атрибутов:
<xsl:element name="element"
use-attribute-sets="elements">
<xsl:apply-templates select="*"/>
</xsl:element>
Именованный набор атрибутов не может прямо или косвенно (посредством других наборов атрибутов) использовать в значении use-attribute-sets себя самого. Такая ситуация породила бы бесконечный цикл. Вообще, не рекомендуется выстраивать сложную иерархию именованных наборов атрибутов, поскольку это может сильно усложнить обработку и снизить эффективность преобразования, хотя, естественно, все зависит от конкретного случая.
Атрибут xsl:use-attribute-sets
Мы упомянули о том, что именованные наборы атрибутов используются в элементах посредством атрибута xsl:use-attribute-sets. Разберем более детально, где этот атрибут может применяться, и какие функции он при этом выполняет. Для удобства эти данные сведены в табл. 7.1.
Таблица 7.1. Использование атрибута xsl:use-attribute-sets
Родительский элемент Особенности использования xsl:attribute-set Включает в определяемый набор атрибутов атрибуты из перечисленных наборов xsl:element Включает в создаваемый элемент атрибуты из перечисленных наборов. Включение эквивалентно текстовому включению — значения атрибутов вычисляются в контексте создающего элемента xsl:element xsl:copy Включает в копируемый элемент атрибуты из перечисленных наборов. Принцип действия— как в случае с xsl:element. Копируемый узел должен быть элементом Литеральный результирующий элемент Принцип действия такой же, как и в случае с xsl:element. В случае совпадения имен, значения атрибутов из набора будут переопределять значения атрибутов самого элемента. При использовании в литеральном элементе, атрибут xsl:use-attribute-sets должен быть обязательным образом объявлен принадлежащим пространству имен XSLT. Как правило, это делается указанием префикса xslСоздание текстовых узлов
Шаблон преобразования может содержать текстовые узлы, которые при выполнении шаблона после обработки пробельных символов будут попросту скопированы в результирующее дерево. Таким образом, для того, чтобы вывести в выходящий документ некоторый текст, можно просто включить его в шаблон преобразования.
Рассмотрим пример.
Листинг 7.11. Входящий документ<answer>No!</answer>
Листинг 7.12. Шаблон преобразования<xsl:template match="answer">