Чтение онлайн

ЖАНРЫ

Технология XSLT

Валиков Алексей Н.

Шрифт:
Пример

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

<xsl:variable name="colors">

 <color>#0E0E0E</color>

 <color>#FFFFFF</color>

</xsl:variable>

создает в переменной

colors
результирующий фрагмент дерева. В соответствии со спецификацией XPath 1.0 выражение
$colors/color[1]
будет некорректным,
поскольку типом
colors
является результирующий фрагмент дерева, который не может быть напрямую преобразован во множество узлов. Иными словами, совершенно логичное и оправданное выражение не является корректным. Конечно, существуют способы обойти этот запрет — с помощью расширений и тому подобного, но нельзя не согласиться с тем, что результирующие фрагменты являются самой большой занозой в XSLT 1.0.

XSLT 1.1 исправляет этот просчет. Переменная

colors
, определенная выше, будет иметь своим значение не фрагмент дерева, а множество из одного, корневого, узла этого фрагмента и ее можно использовать везде, где только можно использовать тип данных
node-set
.

Несколько выходящих документов

Как известно, преобразование в XSLT 1.0 имеет один основной входящий документ (плюс документы, доступные при помощи функции

document
) и ровно один выходящий документ. То есть, для того, чтобы сгенерировать на основе одного входящего документа несколько выходящих следует просто выполнить несколько преобразований.

Следуя многочисленным запросам программистов, почти все разработчики XSLT-процессоров предоставили в своих продуктах возможность генерировать несколько выходящих документов непосредственно из одного преобразования. Элемент

xsl:document
, добавленный в XSLT 1.1, сделал эту возможность стандартной.

Пример

Самым простым применением

xsl:document
является разбиение одного документа на несколько. Например, имея документ вида

<book>

 <chapter>Text 1</chapter>

 <chapter>Text 2</chapter>

 <chapter>Text 3</chapter>

</book>

мы можем выделить элементы

chapter
в отдельные файлы, а в самом выходящем документе создать оглавление со ссылками.

Листинг 12.1. Преобразование, использующее элемент xsl:document

<xsl:stylesheet

 version="1.1"

 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

 <xsl:template match="book">

<xsl:copy>

<xsl:apply-templates select="chapter"/>

</xsl:copy>

 </xsl:template>

 <xsl:template match="chapter">

<chapter href="#"/>

<xsl:document href="#">

<xsl:copy-of select="."/>

</xsl:document>

 </xsl:template>

</xsl:stylesheet>

Результатом этого преобразования будут следующие четыре документа.

Листинг 12.2. Главный выходящий документ преобразования

<book>

 <chapter href="#"/>

 <chapter href="#"/>

 <chapter href="#"/>

</book>

Листинг 12.3.
Документ chapter1.xml

<chapter>Text 1</chapter>

Листинг 12.4. Документ chapter2.xml

<chapter>Text 2</chapter>

Листинг 12.5. Документ chapter3.xml

<chapter>Text 3</chapter>

Дополнительные возможности по расширению

В XSLT 1.1 был введен элемент

xsl:script
, предоставляющий дополнительные возможности для создания и использования функций расширения. При помощи
xsl:script
функции расширения могут быть явным образом определены в самом преобразовании.

Пример

В процессоре, который поддерживает скриптовые языки типа JavaScript, исходный код функций расширения может включаться в само преобразование, например.

Листинг 12.6. Преобразование, включающее функцию расширения

<xsl:stylesheet

 version="1.1"

 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"

 xmlns:js="javascript:code">

 <xsl:script language="javascript" implements-prefix="js">

function iff(arg1, arg2, arg3) {

if (arg1) {

return arg2;

} else {

return arg3;

}

}

 </xsl:script>

 ...

</xsl:stylesheet>

Атрибут

implements-prefix
(англ. implements prefix — реализует префикс) связывает определяемую функцию с некоторым пространством имен (как мы отмечали ранее, все функции расширения должны принадлежать ненулевым пространствам имен). При вызове функций из этого пространства имен в XPath-выражениях, процессор будет искать их определения в элементах
xsl:script
, которые реализуют соответствующий префикс.

Атрибут

language
определяет язык программирования, в котором написано расширение. Очевидно, язык влияет на то, как будет выполняться расширение — например, должен ли процессор интерпретировать содержимое
xsl:script
или следует загрузить внешний Java-класс. Естественно, не следует ожидать, что любой процессор сможет выполнять расширения, написанные на произвольных языках программирования — как правило, разработчики XSLT-средств в документации к своим продуктам оговаривают, какие языки расширения они поддерживают. Как следствие, преобразование, использующее расширения, написанные на "непонятном" процессору языке, либо не будут выполнены вообще, либо будут выполнены некорректно.

Помимо двух обязательных атрибутов

implements-prefix
и
language
, в элемент
xsl:script
могут быть включены атрибуты
src
и
archive
, которые указывают физическое местоположение кода расширения.

"Внешние" типы данных

Четыре основных типа данных языка XPath (булевый, численный, строковый типы и множества узлов) в первой версии XSLT были расширены типом результирующего фрагмента дерева. В некотором смысле, фрагменты деревьев были "внешним" типом по отношению к XPath, но, тем не менее, многие из функций базовой библиотеки с успехом с этим типом работали.

Поделиться с друзьями: