Алексей Валиков - Технология XSLT
<xsl:processing-instruction name="xml-stylesheet">
<xsl:text>href="style.xsl" type="text/xsl"</xsl:text>
</xsl:processing-instruction>
Результирующий документ будет содержать инструкцию по обработке в виде:
<?xml-stylesheet href="style.xsl" type="text/xsl"?>
Элемент xsl:processing-instruction не может создать декларацию XML, несмотря на то, что с точки зрения синтаксиса (но не семантики) она имеет форму инструкции по обработке. Для вывода XML-декларации следует использовать элемент xsl:output.
Копирование узлов
Преобразование может включать в себя не только создание новых, но и копирование существующих узлов. Для этого можно использовать элементы xsl:copy и xsl:copy-of, использование которых будет подробно разобрано ниже.
Элемент xsl:copy
Ниже представлена синтаксическая конструкция этого элемента:
<xsl:copy
use-attribute-sets = "наборы атрибутов">
<!-- Содержимое: шаблон -->
</xsl:copy>
Элемент xsl:copy создает копию текущего узла вне зависимости от его типа. Вместе с текущим узлом в выходящее дерево копируются только узлы пространств имен, ассоциированные с ним. Дочерние узлы и узлы атрибутов в выходящий документ не копируются.
Если xsl:copy используется для копирования корневого узла или узда элемента, в выходящем документе процессор создает дочерний фрагмент дерева, являющийся результатом выполнения шаблона, содержащегося в xsl:copy.
ПримерПредположим, что в каждый элемент преобразовываемого документа нам нужно добавить атрибут element-count со значением, равным количеству его дочерних элементов, а все остальные узлы оставить, как есть.
Листинг 7.17. Входящий документ<а> text
<b attr="value"/>
<c/>
<d>
text
<e/>
</d>
</a>
Листинг 7.18. Шаблон преобразования<xsl:template match="@*|node()">
<xsl:copy>
<xsl:attribute name="element-count">
<xsl:value-of select="count(*) "/>
</xsl:attribute>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
Листинг 7.19. Выходящий элемент<a element-count="3">
text
<b element-count="0" attr="value"/>
<c element-count="0"/>
<d element-count="1">
text
<e element-count="0"/>
</d>
</a>
Если xsl:copy используется для создания в выходящем документе копии узла элемента, в него при помощи атрибута use-attribute-sets могут быть также включены именованные наборы атрибутов (см. раздел "Именованные наборы атрибутов" данной главы).
ПримерПредыдущее преобразование может быть переписано в виде
<xsl:attribute-set name="elements">
<xsl:attribute name="element-count">
<xsl:value-of select="count(*)"/>
</xsl:attribute>
</xsl:attribute-set>
<xsl:template match="@*|node()">
<xsl:copy use-attribute-sets="elements">
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
Результат преобразования будет абсолютно идентичен выходящему документу, полученному в предыдущем примере.
Элемент xsl:copy-of
Синтаксис элемента несложен:
<xsl:copy-of
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 копирует в выходящий документ все узлы в порядке просмотра документа вместе с их потомками.
□ Если результатом вычисления является результирующий фрагмент дерева, то он копируется в выходящий документ в неизмененном виде.
Рассмотрим пример.
Листинг 7.20. Входящий документ<values>
<boolean>false</boolean>
<string>text</string>
<number>3.14</number>
<node-set>
<item>10</item>
<item>20</item>
<item>30</item>
</node-set>
<tree>
text
<root>
text
<branch>
text
<leaf/>
<leaf/>
</branch>
<leaf/>
</root>
</tree>
</values>
Листинг 7.21. Преобразование<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<xsl:variable name="boolean" select="values/boolean='true'"/>
<xsl:variable name="string" select="string(values/string)"/>
<xsl:variable name="number" select="number(values/number)"/>
<xsl:variable name="node-set" select="values/node-set/*"/>
<xsl:variable name="tree">
<xsl:copy-of select="values/tree/*"/>
</xsl:variable>
<xsl:text> Value-of boolean:</xsl:text>
<xsl:value-of select="$boolean"/>
<xsl:text> Copy-of boolean:</xsl:text>
<xsl:copy-of select="$boolean"/>
<xsl:text> Value-of string:</xsl:text>
<xsl:value-of select="$string"/>
<xsl:text> Copy-of string:</xsl:text>
<xsl:copy-of select="$string"/>
<xsl:text> Value-of number:</xsl:text>
<xsl:value-of select="$number"/>
<xsl:text> Copy-of number:</xsl:text>
<xsl:copy-of select="$number"/>
<xsl:text> Value-of node-set:</xsl:text>
<xsl:value-of select="$node-set"/>
<xsl:text> Copy-of node-set:</xsl:text>
<xsl:copy-of select="$node-set"/>
<xsl:text> Value-of tree:</xsl:text>
<xsl:value-of select="$tree"/>
<xsl:text> Copy-of tree:</xsl:text>
<xsl:copy-of select="$tree"/>
</xsl:template>
</xsl:stylesheet>
Листинг 7.22. Выходящий документ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:<item>10</item><item>20</item><item>30</item>
Value-of tree:
text
text
Copy-of tree:<root>
text
<branch>
text
<leaf/>
<leaf/>
</branch>
<leaf/>
</root>
Условная обработка
В XSLT имеются две инструкции, которые поддерживают условную обработку — xsl:if и xsl:choose. Инструкция xsl:if позволяет создавать простые условия типа "если-то", в то время как xsl:choose создает более сложную конструкцию для выбора одной из нескольких имеющихся возможностей в зависимости от выполнения тех или иных условий.
Элемент xsl:if
Синтаксис элемента следующий:
<xsl:if
test="выражение">
<!-- Содержимое: шаблон -->
</xsl:if>
Элемент xsl:if является простейшим условным оператором в XSLT. Выражение, содержащееся в обязательном атрибуте test, вычисляется и приводится к булевому типу. В том и только том случае, если выражение имеет значение true, процессор выполняет шаблон, содержащийся в xsl:if.
Вследствие того, что атрибуты в XML не могут содержать некоторые специальные символы (такие как "<" и "&"), их необходимо заменять символьными сущностями. В особенности это касается сравнения чисел типа "меньше"; объявление вида
<xsl:if test="a < b"/>
будет с точки зрения синтаксиса XML некорректным. Вместо него следует использовать эквивалентное объявление
<xsl:if test="a < b"/>
Следует заметить, что символ "больше" (">") заменять сущностью необязательно. Однако из соображений единообразия принято заменять и его.
ПримерПредположим, мы преобразовываем список названий
<list active="Bravo">
<item>Alpha</item>