KnigaRead.com/

Алексей Валиков - Технология XSLT

На нашем сайте KnigaRead.com Вы можете абсолютно бесплатно читать книгу онлайн Алексей Валиков, "Технология XSLT" бесплатно, без регистрации.
Перейти на страницу:

□ Если текущему токену предшествует другой токен, причем этот предшествующий токен не является символом @, ::, (, [ или нетерминалом Operator, то текущий токен, являющийся символом *, должен восприниматься как знак умножения, а токен, являющийся NCName, — как нетерминал OperatorName.

□ Если за текущим токеном вида NCName следует открывающая круглая скобка (символ "("), токен должен восприниматься или как имя функции (FunctionName), или как тип узла (NodeType).

□ Если за текущим токеном вида NCName следуют символы "::", токен должен восприниматься как имя оси навигации (AxisName).

□ Если ничего из вышеперечисленного не выполняется, токен не должен восприниматься, как MultiplyOperator, OperatorName, NodeType, FunctionName или AxisName.

Мы привели эти правила в точности так, как они описаны в спецификации языка XPath. Их довольно непросто понять в такой формулировке, поэтому мы попытаемся объяснить их другими словами.

□ Символ * является знаком умножения (MultiplyOperator) тогда и только тогда, когда ему предшествует токен, но этот токен не является токеном @, ::, (, [ или Operator.

□ Токен NCName представляет имя оператора (OperatorName) тогда и только тогда, когда ему предшествует токен, но этот токен не является токеном ::, (, [ или Operator.

□ Токен NCName является именем функции (FunctionName) или типом узла (NodeType) тогда и только тогда, когда за ним следует символ "(".

□ Токен NCName является именем оси навигации (AxisName) тогда и только тогда, когда за ним следуют символы "::".

Глава 7

Основные элементы XSLT

Основные и дополнительные элементы

Все элементы XSLT можно разделить на две группы: элементы основные и элементы дополнительные. Это разделение очень условно, ничего подобного в спецификации языка XSLT нет, однако, мы будем им пользоваться, считая основными элементами те элементы XSLT, которые непосредственно отвечают за создание узлов выходящего дерева или обеспечивают контроль над этим процессом. К дополнительным элементам мы будем относить все остальные элементы XSLT.

Таким образом, множество основных элементов будет включать в себя следующее:

□ xsl:element — создание в выходящем дереве узла элемента;

□ xsl:attribute — создание в выходящем дереве узла атрибута;

□ xsl:attribute-set — определение именованного набора атрибутов;

□ xsl:text — создание текстового узла;

□ xsl:value-of — создание текстового узла по результатам вычисления выражения;

□ xsl:comment — создание узла комментария;

□ xsl:processing-instruction — создание узла инструкции по обработке;

□ xsl:copy — копирование текущего узла вместе с его узлами пространств имен;

□ xsl: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. Это выражение выбирает множество, состоящее из узлов атрибутов текущего элемента, а если привести его к строке, в результате получится текстовое значение первого атрибута элемента.

Подобным образом выбирается имя атрибута создаваемого элемента и его значение.

Вычисленное значение атрибута 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 на определение пространства имен, приведем несколько правил, которые пояснят этот процесс.

Перейти на страницу:
Прокомментировать
Подтвердите что вы не робот:*