Языки информационного обмена

Трансформация документа XML

Разбить на страницы
Показывать лекцию целиком

Причины трансформации XML

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

Структурные трансформации - трансформация одного словаря XML в другой по аналогии с переводом.

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

Трансформации в язык формирования изображения - подготовка документа для визуального представления в какой-либо форме браузера пользователя, например в Wireless Application Protocol ( WAP ), HTML, VOXML или в формате масштабируемой векторной графики.

Теперь рассмотрим эти три категории по очереди.

Трансляция между различными словарями

Рассмотрим книжный каталог, размеченный на языке XML. Данные этого каталога можно использовать различными способами. Например, используя определение DTD, компания Wrox может разместить каталог на своем Web-сайте и в корпоративной сети Интранет. Книжные магазины требуют практически такую же информацию, что делает язык XML идеальным кандидатом для ее передачи. Однако, если разные книжные магазины используют для описания одних и тех же данных разные DTD, необходим способ трансформации наших данных в совместимую с ними версию.

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

Трансформации - ценное свойство в мире XML, особенно когда необходимо изменить назначение данных, размеченных на этом языке. Помимо прочего, если можно обойтись одной простой трансформацией, нет необходимости обслуживать две версии данных. Для таких трансформаций идеально подходят возможности, предлагаемые языком XSL.

Динамические трансформации

В предыдущем разделе было описано представление одних и тех же данных различными способами, и при этом все участники требовали конкретных статических версий документов XML. Однако иногда возникает необходимость в более динамической трансформации. Например, в электронных таблицах часто в ответ на щелчок мышью на заголовке столбца требуется отсортировать данные. Для этого нужны более динамичные трансформации.

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

Такие трансформации можно осуществлять и без помощи XSL, используя языки сценариев и модель DOM, а модель DOM можно применять в браузерах благодаря ее совместимости с языками JavaScript, Java, C++, Perl, Visual Basic или Python. Поэтому часто при осуществлении трансформаций обходятся только моделью DOM и языками сценариев (без XSL ).

Различные браузеры

Многие Web-разработчики затратили огромные усилия и получили головную боль, пытаясь создать параллельные сайты или части сайтов для несовместимых версий браузеров. Мысль о том, что XML применим только в браузерах, понимающих этот язык, предполагает появление еще одной области несовместимости. Однако, разработав содержание сайта на языке XML, можно затем трансформировать его в другие языки разметки, чтобы из одного центрального содержания XML создать несколько версий документов HTML.

XSL

Расширяемый язык таблиц стилей( XSL ) основан на XML и предназначен для трансформации документа XML в другой документ XML или в объекты визуализации. Первоначальный язык XSL распался на три отдельных языка:

  • Язык трансформаций ( XSLT )
  • Язык визуализации ( XSLF ; он может использовать также и XSLT )
  • Язык обращений к структуре, на которой основаны документы XML ( XPath )
  • Язык XSL основан на каскадных таблицах стилей ( Cascading Style Sheets, CSS ) и на языке DSSSL ( Document Style Semantics and Specification Language - язык спецификации и семантики стиля документа). По мере развития XSL его аспекты моделирования (работы со стилями) все ближе к CSS и отходят от DSSSL.

    XSLT

    XSLT является языком, для трансформации документов XML в другие документы XML. Для этого необходим процессор XSLT.

    Язык XSLT написан на XML. Это означает, что обеспечивающая трансформацию документа XML таблица стилей XSLT является правильно оформленным документом XML. Прежде всего следует уяснить что обработчики XSLT работают не с документами, а со структурами.

    Чтобы процессор XSLT смог трансформировать документ XML, последний должен сначала быть преобразован в структуру или во внутреннюю модель. Эта внутренняя модель представляет собой дерево и не зависит от используемых для доступа к ней интерфейсов API. В мире SGML такая абстрактная модель называется рощей. Поскольку язык XML является подмножеством SGML, он наследует его основные концепции. Итак, роща представляет собой просто абстрактную древовидную структуру, не зависящую от интерфейсов API, используемых для доступа к объектам этой структуры или для манипуляции ими. Например, для доступа к роще консорциум W3C рекомендовал модель DOM. Поэтому DOM представляет собой API, а роща - абстрактную структуру. У рощи может быть несколько интерфейсов API или для разных языков могут быть разработаны различные интерфейсы.

    Каким образом процессор XSL трансформирует исходный документ

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

    Язык XSLT является декларативным, т.е. вы определяете, как должен выглядеть результат, а не как он должен быть трансформирован; именно для выполнения этой работы нужен процессор XSL. Таблица стилей XSL состоит из шаблонов (templates), определяющих, каким образом каждый узел исходного дерева должен быть представлен в дереве результата. Процессор проходит по роще источника, начиная с корня, и ищет соответствующие шаблоны в дереве таблицы стилей. Обнаружив шаблон, он с помощью содержащихся в нем правил записывает абстрактное представление результата в дерево результата. Так он перемещается по документу узел за узлом (это определяется инструкцией XSLT <xsl:apply-template> ) и ищет соответствия в таблице стилей. Если соответствующего шаблона не обнаруживается, он переходит к следующему. Можно сказать, что в таком случае он выполняет шаблон по умолчанию, который не приводит к результату на выходе. По завершении работы процессора дерево результата можно транслировать в документ XML, текст, документ HTML или в другую желаемую форму.

    Теоретически события должны происходить в описанной последовательности. Однако в методах создания обработчиков XSLT используются различные вариации. Процессоры XSLT можно оптимизировать, а таблицы стилей не обязательно сохранять в виде рощи или древовидной структуры. Тем не менее описанный подход дает общее представление об их поведении.

    Трансформация документа таблицей стилей

    Язык XSL является приложением XML, так что фактически таблица стилей (т.е. таблица трансформаций) представляет собой документ XML. В связи с этим документ может начинаться с декларации XML, показывающей анализатору, какой версией языка документ закодирован.

    Корневым элементом нашей таблицы стилей является элемент <xsl: stylesheet>:

    <xsl: stylesheet version=="1.0"
    xmlns:xsl=="http://www.w3.org/1999/XSL/Transform">.

    Первым атрибутом этого элемента служит версия XSLT, вторым - атрибут xmlns:xsl, содержащий пространство имен для рекомендации трансформации XSL.

    Этот атрибут декларирует пространство имен ХSLT. С данным пространством связан префикс xsl, так что корневым элементом фактически является элемент <stylesheet>, но он квалифицирован префиксом пространства имен xsl:. После объявления пространства имен любой элемент начинающийся с префикса xsl:, входит в состав словаря XSL.

    Элемент <stylesheet> содержит три шаблона, каждый из которых вложен в элемент <template>. В таблице стилей этот элемент фактически называется <xsl:template>, так как мы включили пространство имен. У элемента <template> есть атрибут match, значением которого является образец ( pattern ) в форме выражения XPath. С ним сравнивается узел дерева, к которому применяется шаблон. Прежде всего процессору XSL надо сообщить желаемую форму вывода. Узнав ожидаемый формат вывода, процессор начнет исследовать исходный документ с корневого узла.

    Образцы (patterns)

    Прежде чем сделать преобразование дерева документа XML, из него следует выбрать те узлы, которые подвергнутся тому или иному преобразованию, Их можно выбирать по имени, содержимому, атрибутам и другим признакам. Условия отбора узлов задаются образцом (pattern), записанным в виде одного или нескольких выражений языка XPath 2.0. Выражения, содержащиеся в образце, объединяются вертикальной чертой |, означающей, что выбираемый узел должен удовлетворять хотя бы одному выражению образца. Вместо вертикальной черты можно записывать слово union.

    В образце можно записать не всякое выражение XPath, а только путь, каждый шаг которого определяется осью, причем допускаются только три оси: child (по умолчанию), // и attribute. Это означает, что, находясь в каком-то узле, мы можем "увидеть", кроме него самого, только его атрибуты и узлы-потомки. Обратите внимание на то, что явная запись оси descendant-or-self недопустима, применяется только сокращенная запись //. Запись оси attribute:: можно сократить до одной "собачки" @, а текущий узел очень часто обозначается точкой.

    Хотя образец и строится как выражение языка XPath, но его цель - не отобрать последовательность узлов, а проверить соответствие узла данному образцу. Можно сказать, что некоторый узел Node соответствует некоторому образцу pattern тогда и только тогда, когда узел Node принадлежит последовательности узлов - результату вычисления выражения //Pattern. Например, образцу person//street будут соответствовать все узлы из последовательности //person//street, а именно все узлы street, вложенные в узлы-элементы person даже через несколько промежуточных узлов.

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

    Функции id() и key()

    Образец может начинаться с вызова функции id() или функции key(). Единственным аргументом функции id() служит уникальный идентификатор узла, т.е. значение его атрибута типа ID. Например, образцу id(@xref) соответствует узел-элемент, на идентификатор которого ссылается значение атрибута xref. Образцу id(<h12>) соответствует узел-элемент с идентификатором h12, а образцу id(<h12>)//street - его потомки street любого уровня вложенности.

    Функция id(), работающая с атрибутами типа ID, подвержена всем ограничениям этого типа, а именно:

  • у элемента может быть только один атрибут типа ID, значит, можно cссылаться только на этот атрибут, не говоря уже о том, что такой атрибут может вообще отсутствовать:
  • значение атрибута типа ID уникально, значит, нельзя обратиться сразу к нескольким элементам;
  • значение атрибута типа ID может быть только именем типа Name, значит, не может быть числом, содержать пробелы и многие другие символы;
  • схема, в которой определен тип ID атрибута, может оказаться недоступной для процессора XSLT и он не "узнает" тип атрибута;
  • функция id() работает только с атрибутами, но не с элементами, их содержимым и прочими узлами дерева документа;
  • для внесения новых перекрестных ссылок в документ XML надо его менять, вставляя атрибуты типа ID, что может быть нежелательно или невозможно.
  • Функция key() менее требовательна. Она снимает ограничения функции id(), обращаясь не к атрибуту элемента, находящегося в документе ХМL, а к атрибуту use специального элемента xsl:key, расположенного в таблице стилей. У нее два аргумента:

  • имя ключа, задаваемое строкой типа QName; это значение атрибута name элемента xsl:key, позволяющее выбрать нужный элемент xsl:key.
  • значение ключа, представляющее собой выражение, в результате вычисления которого получается последовательность из одного или нескольких атомарных значений типа xdt:anyAtomicType.
  • Образец с функцией key() выглядит примерно так:
    key("addr", 230007)//street.

    Элемент xsl:key определяет ключ и множество значений, а функция key() выбирает из этого множества те значения, что совпадают со вторым аргументом функции key(). Таким образом, при необходимости создания новых ссылок в исходном документе XML, его не надо изменить, достаточно добавить новые элементы xml:key в таблицу стилей.

    Элементы, объявленные в XSLT

    Язык XSLT объявляет около полусотни элементов. Из них 17 элементов верхнего уровня, которые могут быть непосредственно вложены в корневой элемент xsl:stylesheet таблицы стилей. Они называются декларациями. Это элементы xsl: import, xsl: include, xsl: attribute-set, xsl:character-map, xsl:date-format, xsl:decimal-format, xsl:function, xsl:import-schema, xsl:key, xsl:namespace-alias, xsl:output, xsl:param, xsl:preserve-space, xsl:sort-key, xsl:strip-space, xsl:template, xsl:variable. Более того, все эти элементы, кроме xsl:param и xsl: variable, можно записывать только на верхнем уровне вложенности, непосредственно в корневом элементе xsl:stylesheet.

    Кроме элементов верхнего уровня вложенности, в языке XSLT объявлено более тридцати элементов, которые можно записывать в теле элементов верхнего уровня. Наиболее часто применяются элементы xsl:apply-templates, xsl:value-of, xsl:copy-of, xsl:sort, xsl:text.

    Из всех элементов XSLT не верхнего уровня вложенности выделяются инструкции. Не путайте инструкции XSLT и инструкции по обработке XML. Формально инструкции XSLT определяются как элементы, которые можно вставлять в конструктор последовательности. К инструкциям, в частности, относятся элементы, создающие узлы всех семи видов и последовательности узлов. Это элементы xsl:element, xsl:attribute, xsl:text, xsl:comment, xsl:processing-instruction, xsl:namespace, xsl:result-document, xsl:sequence.

    Кроме них, инструкциями считаются элементы xsl:apply-templates, x sl: value-of, xsl: variable и др., всего более двадцати элементов. К инструкциям относятся как элементы, управляющие выбором правил преобразовании xsl:if, xsl:for-each, xsl:choose, так и элементы, копирующие узлы xsl:copy, xsl:copy-of.

    Все элементы необязательны и могут располагаться в любом порядке, за одним исключением: декларации xsl:import, если они есть, должны быть записаны первыми.

    Рассмотрим некоторые наиболее часто применяемые элементы XSLT.

    Декларация xsl:import

    Элемент xsl:import записывается очень просто:

    <хsl:import href="адрес URI таблицы стилей" />

    Его можно записать только непосредственно в корневом элементе xsl:stylesheet и только в самом начале таблицы стилей. Элементов xsl: import может быть несколько.

    Процессор XSLT отыскивает таблицу стилей по указанному атрибутом href адресу и подставляет ее на место элемента xsl:import перед преобразованием.

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

    Декларация xsl:include

    Второй элемент, включающий внешние таблицы стилей в данную таблицу, - это элемент xsl:include. Он записывается точно так же, как элемент xsl:import, и оказывает такое же действие:

    <xsl:include href="адрес URI таблицы стилей" />

    Его можно записать не только непосредственно в корневом элементе xsl:stylesheet, но, в отличие от элемента xsl:import, в любом месте таблицы стилей. Второе отличие от элемента xsl:import заключается в том, что порядок записи элементов xsl:include в таблице стилей не имеет значения.

    Декларация xsl:variable

    Элемент xsl:variable определяет имя объекта. Оно записывается обязательным атрибутом name. Имя объекта должно быть уточненным именем XML типа QName. Кроме того, атрибутом select переменной можно задать сам объект, а атрибутом as определить тип объекта. Например:

    <xsl:variable name="var1" select="count(//person)" as="xs:integer" />

    Имя var1 будет хранить число элементов person. Объект может быть получен из содержимого элемента xsl: variable:

    <xsl: variable name="var2">10</xsl:variable>

    или создан конструктором последовательности:

    <xsl:variable name="var3">
    <xsl:value-of select="count (//person) " /> 
    <xsl:variable>

    Если объект не получен из атрибута select или содержимого элемента xsl: variable, то по умолчанию имя связывается с пустой строкой.

    Для того чтобы получить объект, связанный с именем, определенным элементом xsl: variable, перед именем надо поставить знак доллара: $varl, $var2. При этом следует учитывать область действия имени.

    Область действия имени простирается на весь элемент, в котором оно определено, начиная с места определения и включая вложенные элементы, если только в них не определено то же самое имя.

    Имена, определенные непосредственно в корневом элементе xsl:stylesheet, называются глобальными именами, остальные - локальными именами.

    Хотя слово "variable" и переводится с английского языка как "переменная", имя, созданное элементом xsl: variable - это не имя переменной, его значение нельзя изменить. Это только название некоторого объекта, которое удобно использовать в тех случаях, когда объект надо использовать во многих местах таблицы стилей, а его вычисление сложно или громоздко.

    Декларация xsl:param

    Элемент xsl:param записывается или непосредственно в элементе xsl:stylesheet, чтобы задать параметр преобразования, или в элементе xsl:template, чтобы задать параметр правила, или в элементе xsl:function как аргумент функции. У него один обязательный атрибут name, определяющий имя параметра. Кроме него, часто присутствует необязательный атрибут select, в котором записывается выражение для получения значения параметра:

    <xsl:param name="pl" select="10 + 20" />

    Если атрибут select отсутствует, то значение параметра берется из содержимого элемента, которым может быть конструктор последовательности узлов и атомарных значений:

    <xsl:param name="p2">10</xsl:param>

    Если отсутствует и атрибут select, и содержимое элемента, то параметр получает значение пустой строки.

    Дли получении значения параметра надо записывать его имя со знаком доллара: $p1,$p2. Например:

    <xsl:when test= "$p1=10 ">

    Правила, определяющие область видимости параметров, такие же, как и у имен объектов, определенных декларацией xsl:variable.

    Еще один необязательный атрибут as содержит желательный тип, к которому будет приведено значение параметра.

    Наконец, последний атрибут required, принимающий значения yes или nо (по умолчанию), указывает обязательность параметра. Если параметр обязателен, required="yes", то элемент xsl:param должен быть пустым и не содержать атрибут select. В таком случае он получит определенное значение при вызове функции или элементом xsl:with-param при вызове шаблона.

    Элемент xsl:with-param

    Элемент xsl:with-param ссылается на некоторый параметр, имя которого записано в обязательном атрибуте name. Необязательным атрибутом select можно задать выражение, результат вычисления которого будет новым значением параметра:

    <xsl:with-param name="pl" select="100 * 20" />

    Новое значение можно задать и в содержимом элемента:

    <xsl:with-param name="pl">100</xsl:with-param>

    Элемент xsl:with-param используется только в инструкциях xsl:apply-templates, xsl:apply-imports, xsl:call-template.

    Инструкция xsl:value-of

    Элемент xsl:value-of вычисляет выражение, записанное в его обязательном атрибуте select, и преобразует его в строку. Например, выше мы определили имя объекта var2. Чтобы получить значение объекта var2, надо записать:

    <xsl:value-of select="$var2" /></example>

    Если в результате вычисления выражения получается последовательность, то процессор XSLT версии 1.0 выберет из нее только первый элемент, преобразованный в строку.

    Инструкции управления xsl:if, xsl:for-each, xsl:choose

    Элемент xsl:if запускает конструктор последовательности, содержащийся в его теле, только если истинно выражение, записанное в обязательном и единственном атрибуте test:

    <xsl:if test="$x > $у">
    <xsl:value-of select="$x"/> больше <xsl:value-of select="$y" />
    </xsl:if>

    У элемента xsl:for-each в обязательном и единственном атрибуте select записывается выражение, дающее в результате последовательность. Для каждого члена этой последовательности выполняется конструктор, содержащийся в теле элемента xsl:for-each. В результате получается цикл, выполняющийся столько раз, сколько элементов у последовательности, полученной в результате вычисления выражения атрибута select.

    У элемента xsl:choose нет ни одного атрибута, но в его теле записывается один или несколько элементов xsl: when и один необязательный элемент xsl:otherwise:

    <xsl:choose>
    <xsl:when test="$day=l">Понедельник</xsl:when>
    <xsl when test="$day=2">Bторник</xsl:when>
    <xsl when test="$day=3">Cреда</xsl:when>
    <xsl when test="$day=4">Четверг</xsl:when>
    <xsl when test="$day=5">Пятница</xsl:when>
    <xsl when test="$day=6">Cyббота</xsl:when>
    <xsl when test="$day=7">Воскресенье</xsl:when>
    <xsl otherwise>Ошибка определения дня нeдeли</xsl:otherwise>
    </xsl:choose>

    У элемента xsl:when есть только один обязательный параметр test, содержащий логическое выражение, и тело, содержащее конструктор последовательности.

    Элемент xsl: otherwise не имеет атрибутов, у него есть только тело, содержащее конструктор последовательности.

    В инструкции xsl: choose всегда выполняется не больше одного варианта, Варианты xsl:when просматриваются в порядке их написания в инструкции xsl:choose. Как только будет найден вариант с истинным значением выражения test, он будет выполнен, и результат этого варианта будет результатом всей инструкции. Варианты, следующие за ним по порядку, не рассматриваются. Если ни один вариант не подойдет, то результатом инструкции будет результат конструктора, записанного в элементе xsl:otherwise. Если элемента xsl:otherwise в инструкции нет, то результатом будет пустая строка.

    Декларация xsl:function

    Элемент xsl:function позволяет описывать самые настоящие пользовательские функции. Имя функции записывается в обязательном атрибуте nаmе, (аргументы функции задаются элементами xsl:param, а тело функции - это конструктор последовательности, записанный в содержимом элементе xsl:function. Результатом функции будет последовательность, созданная конструктором. Тип функции можно указать необязательным атрибутом аs.

    Имя функции - это уточненное имя типа QName, причем оно должно обязательно записываться с префиксом.

    Все аргументы функции позиционные, следовательно, все элементы xsl:param должны быть записаны в начале тела функции и порядок их записи имеет значение при вызове функции. У аргументов функции не может быть значений по умолчанию, следовательно, элементы xsl:param должны быть пустыми и у них не должно быть атрибутов select. Например:

    <xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:usr="http://myexamples.com"
    xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xsl: function name= " usr:sum "  as="xsl:integer">
    <xsl:param name="x" as="xsl:integer" />
    <xsl:param name="y" as="xsl:integer" />
    <xsl:value-of select="$x + $y" /> 
    </xsl:function>

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

    <хsl:value-of select="10 + 2 * usr:sum(2, 3)" />

    Функция может вызываться рекурсивно.

    Декларация xsl:template

    Элемент xsl:template определяет шаблонное правило преобразования. Своим атрибутом match он задает образец для отбора узлов, подлежащих преобразованию, а в теле содержит конструктор последовательности узлов и атомарных значений, которая и будет результатом преобразования отобранных по образцу узлов.

    <xsl: template match=" Образец" name="Имя">Конструктор</хsl:template>

    Каждый из атрибутов match и name не обязателен, но хотя бы один из них должен присутствовать.

    Атрибут match содержит образец для отбора преобразуемых узлов.

    Атрибут name определяет имя шаблона. Имя шаблона - это обычное уточненное имя XML типа QName. Шаблон можно вызвать по имени элементом xsl:call-template, а если он не содержит атрибута match, то такой вызов обязателен, поскольку неизвестны узлы, к которым его надо применить, и он не будут применяться автоматически. Очень часто именованный шаблон содержит параметры, заданные элементами xsl:param, и вызывается с различными параметрами совсем как обычная функция.

    У элемента xsl: template могут быть дополнительные атрибуты mode, as, priority.

    Атрибут mode определяет режим обработки.

    Атрибут as указывает желаемый тип результата (полученная последовательность будет приведена к этому типу).

    Атрибут priority назначает правилу приоритет, который будет учитываться при отборе правил, применимых к некоторому узлу.

    При вызове именованного шаблона элементов xsl:call-template атрибуты match, mode и priority игнорируются.

    Если у именованного шаблона нет атрибута match, то у него не должно быть и атрибутов mode и priority, в них просто нет никакого смысла.

    Инструкция xsl:apply-templates

    Элемент xsl:apply-templates, записываемый чаще всего внутри элемента xsl: template, в простейшем виде пуст:

    <xsl:apply-templates />

    Он предписывает обработать рекурсивно все узлы-потомки узлов, отобранных родительским элементом xsl:template.

    У элемента xsl:apply-templates есть необязательные атрибуты select и mode.

    Атрибут select, значением которого должно быть выражение, дающее последовательность узлов, ограничивает обработку только указанными в нем узлами.

    Атрибут mode выбирает режим обработки из режимов, уже определенных в элементах xsl:template. Режим - это любое имя типа QName, но два режима предопределены. Это текущий режим, отмечаемый словом #current, и режим по умолчанию, принимаемый при отсутствии атрибута mode, или отмечаемый явно словом #default.

    Содержимым элемента xsl: apply-templates могут служить элементы xsl:sort и xsl:with-param.

    Инструкция xsl:for-each-group

    Элемент xsl:for-each-group отбирает последовательность узлов и атомарных значений своим обязательным атрибутом select и группирует ее элементы по признаку, заданному выражением, записанным в атрибуте group-by. Этот признак называется ключом группы. Ключ группы вычисляется заново для каждого элемента последовательности. В результате исходная последовательность, отобранная атрибутом select, разбивается на несколько последовательностей. В следующем примере в одну группу собираются все узлы-элементы name с одинаковым значением атрибута surname:

    <xsl:for-each-group select="name" group-by="@surname">

    Выражение, являющееся значением атрибута group-by, может давать несколько ключей группы, и один узел может попасть сразу в несколько групп. Например:

    <xsl:for-each-group select="name" group-by="(@second, @surname)">

    Второй способ разбить последовательность на группы дает атрибут group-adjacent. Он собирает в группу все подряд идущие элементы последовательности с одинаковым значением ключа. Такой отбор возможен, если в атрибуте group-adjacent содержится только один ключ группы. Процессор XSLT следит за тем, чтобы значением атрибута group-adjacent был один и только один ключ группы.

    Третий и четвертый способы применимы к последовательностям, состоящим только из узлов, без атомарных значений. Эти способы применяют атрибут group-starting-with или атрибут group-ending-with. Значением этих атрибутов может быть не любое выражение, а только образец. В одну группу собираются все подряд идущие узлы, первый (последний) из которых удовлетворяет образцу. Остальные узлы из этой группы не будут удовлетворять образцу. Если несколько подряд идущих элементов последовательности удовлетворяют образцу, то они попадут в разные группы.

    Итак, группы узлов создаются одним из четырех атрибутов элемента xsl:for-each-group: group-by, group-adjacent, group-starting-with, group-ending-with. В каждом элементе xsl:for-each-group должен быть один и только один из этих атрибутов. Полученные группы существуют и могут использоваться только в содержимом элемента xsl:for-each-group. В теле элемента xsl:for-each-group записывается конструктор последовательности, который выполняется по одному разу для каждой группы.

    Для удобства работы с группами в язык XSLT введены функции current-group() и current-group-key ().Их можно использовать только в теле элемента xsl:for-each-group. У обеих функций нет аргументов. Результатом функции current-group() будет последовательность- текущая группа, а результатом функции current-group-key() - значение ключа текущей группы.

    Функции процессора XSL

  • Во-первых, процессор строит рощу, являющуюся внутренним представлением документа. Эта роща всегда имеет корневой элемент, представляющий собой весь документ XML, а не его элемент верхнего уровня. Ниже корневого элемента расположена вся иерархия узлов. Каждый узел типизирован. Например, он может быть предназначен для определения DTD, для схемы или для команды обработки. Если элемент содержит атрибуты, то у каждого элемента также имеется коллекция узлов атрибутов. Если элемент содержит данные, то в узел элемента вкладывается еще и соответствующие им узел. Таким образом, потомками узла элемента может быть коллекция узлов атрибутов и узел данных.
  • Во-вторых, создает структуру для документа XSLT. Она также может представлять собой рощу, но может быть структурой любого типа, оптимизированной для обработки шаблонов и соответствия образцов.
  • Затем каждый раз, встретив элемент <xsl: apply-templates>, формирует список узлов и продолжит работу с этим списком. Если элемент <xsl:apply-templates> содержит атрибут select, список узлов формируется на основе указанного запроса XPath. В противном случае список содержит все дочерние узлы.
  • Каждый раз, встретив конструкцию <xsl: value-of>, процессор извлекает значение из исходного дерева, основываясь на выражении XPath ее атрибута select.
  • Трансформация не ограничивается только трансляцией типа один-к-одному: она позволяет добавлять новое информационное содержание, добавлять и удалять элементы, а также осуществлять трансляции типа один-ко-многим.
  • Трансформация документа XML с помощью модели DOM

    Документ XML можно трансформировать и с помощью модели DOM, являющейся интерфейсом для представления документа в виде дерева. Однако такой способ трансформации документа является несколько рискованным, поскольку большинство реализации DOM содержит множество частных, свойственных только им конструкций. Например, даже в рекомендациях по DOM 2 не указано, каким образом загружать или сохранять документы XML, поэтому те, кто занимается их реализацией, должны изобретать свои методы для этих фундаментальных операций. В результате большинство сценариев, используемых для трансформации документов XML, не будут переносимыми, поскольку, как правило, содержат различные частные конструкции

    Страницы:

    Причины трансформации XML

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

    Структурные трансформации - трансформация одного словаря XML в другой по аналогии с переводом.

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

    Трансформации в язык формирования изображения - подготовка документа для визуального представления в какой-либо форме браузера пользователя, например в Wireless Application Protocol ( WAP ), HTML, VOXML или в формате масштабируемой векторной графики.

    Теперь рассмотрим эти три категории по очереди.

    Трансляция между различными словарями

    Рассмотрим книжный каталог, размеченный на языке XML. Данные этого каталога можно использовать различными способами. Например, используя определение DTD, компания Wrox может разместить каталог на своем Web-сайте и в корпоративной сети Интранет. Книжные магазины требуют практически такую же информацию, что делает язык XML идеальным кандидатом для ее передачи. Однако, если разные книжные магазины используют для описания одних и тех же данных разные DTD, необходим способ трансформации наших данных в совместимую с ними версию.

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

    Трансформации - ценное свойство в мире XML, особенно когда необходимо изменить назначение данных, размеченных на этом языке. Помимо прочего, если можно обойтись одной простой трансформацией, нет необходимости обслуживать две версии данных. Для таких трансформаций идеально подходят возможности, предлагаемые языком XSL.

    Динамические трансформации

    В предыдущем разделе было описано представление одних и тех же данных различными способами, и при этом все участники требовали конкретных статических версий документов XML. Однако иногда возникает необходимость в более динамической трансформации. Например, в электронных таблицах часто в ответ на щелчок мышью на заголовке столбца требуется отсортировать данные. Для этого нужны более динамичные трансформации.

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

    Такие трансформации можно осуществлять и без помощи XSL, используя языки сценариев и модель DOM, а модель DOM можно применять в браузерах благодаря ее совместимости с языками JavaScript, Java, C++, Perl, Visual Basic или Python. Поэтому часто при осуществлении трансформаций обходятся только моделью DOM и языками сценариев (без XSL ).

    Различные браузеры

    Многие Web-разработчики затратили огромные усилия и получили головную боль, пытаясь создать параллельные сайты или части сайтов для несовместимых версий браузеров. Мысль о том, что XML применим только в браузерах, понимающих этот язык, предполагает появление еще одной области несовместимости. Однако, разработав содержание сайта на языке XML, можно затем трансформировать его в другие языки разметки, чтобы из одного центрального содержания XML создать несколько версий документов HTML.

    XSL

    Расширяемый язык таблиц стилей( XSL ) основан на XML и предназначен для трансформации документа XML в другой документ XML или в объекты визуализации. Первоначальный язык XSL распался на три отдельных языка:

  • Язык трансформаций ( XSLT )
  • Язык визуализации ( XSLF ; он может использовать также и XSLT )
  • Язык обращений к структуре, на которой основаны документы XML ( XPath )
  • Язык XSL основан на каскадных таблицах стилей ( Cascading Style Sheets, CSS ) и на языке DSSSL ( Document Style Semantics and Specification Language - язык спецификации и семантики стиля документа). По мере развития XSL его аспекты моделирования (работы со стилями) все ближе к CSS и отходят от DSSSL.

    XSLT

    XSLT является языком, для трансформации документов XML в другие документы XML. Для этого необходим процессор XSLT.

    Язык XSLT написан на XML. Это означает, что обеспечивающая трансформацию документа XML таблица стилей XSLT является правильно оформленным документом XML. Прежде всего следует уяснить что обработчики XSLT работают не с документами, а со структурами.

    Чтобы процессор XSLT смог трансформировать документ XML, последний должен сначала быть преобразован в структуру или во внутреннюю модель. Эта внутренняя модель представляет собой дерево и не зависит от используемых для доступа к ней интерфейсов API. В мире SGML такая абстрактная модель называется рощей. Поскольку язык XML является подмножеством SGML, он наследует его основные концепции. Итак, роща представляет собой просто абстрактную древовидную структуру, не зависящую от интерфейсов API, используемых для доступа к объектам этой структуры или для манипуляции ими. Например, для доступа к роще консорциум W3C рекомендовал модель DOM. Поэтому DOM представляет собой API, а роща - абстрактную структуру. У рощи может быть несколько интерфейсов API или для разных языков могут быть разработаны различные интерфейсы.

    Каким образом процессор XSL трансформирует исходный документ

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

    Язык XSLT является декларативным, т.е. вы определяете, как должен выглядеть результат, а не как он должен быть трансформирован; именно для выполнения этой работы нужен процессор XSL. Таблица стилей XSL состоит из шаблонов (templates), определяющих, каким образом каждый узел исходного дерева должен быть представлен в дереве результата. Процессор проходит по роще источника, начиная с корня, и ищет соответствующие шаблоны в дереве таблицы стилей. Обнаружив шаблон, он с помощью содержащихся в нем правил записывает абстрактное представление результата в дерево результата. Так он перемещается по документу узел за узлом (это определяется инструкцией XSLT <xsl:apply-template> ) и ищет соответствия в таблице стилей. Если соответствующего шаблона не обнаруживается, он переходит к следующему. Можно сказать, что в таком случае он выполняет шаблон по умолчанию, который не приводит к результату на выходе. По завершении работы процессора дерево результата можно транслировать в документ XML, текст, документ HTML или в другую желаемую форму.

    Теоретически события должны происходить в описанной последовательности. Однако в методах создания обработчиков XSLT используются различные вариации. Процессоры XSLT можно оптимизировать, а таблицы стилей не обязательно сохранять в виде рощи или древовидной структуры. Тем не менее описанный подход дает общее представление об их поведении.

    Трансформация документа таблицей стилей

    Язык XSL является приложением XML, так что фактически таблица стилей (т.е. таблица трансформаций) представляет собой документ XML. В связи с этим документ может начинаться с декларации XML, показывающей анализатору, какой версией языка документ закодирован.

    Корневым элементом нашей таблицы стилей является элемент <xsl: stylesheet>:

    <xsl: stylesheet version=="1.0"
    xmlns:xsl=="http://www.w3.org/1999/XSL/Transform">.

    Первым атрибутом этого элемента служит версия XSLT, вторым - атрибут xmlns:xsl, содержащий пространство имен для рекомендации трансформации XSL.

    Этот атрибут декларирует пространство имен ХSLT. С данным пространством связан префикс xsl, так что корневым элементом фактически является элемент <stylesheet>, но он квалифицирован префиксом пространства имен xsl:. После объявления пространства имен любой элемент начинающийся с префикса xsl:, входит в состав словаря XSL.

    Элемент <stylesheet> содержит три шаблона, каждый из которых вложен в элемент <template>. В таблице стилей этот элемент фактически называется <xsl:template>, так как мы включили пространство имен. У элемента <template> есть атрибут match, значением которого является образец ( pattern ) в форме выражения XPath. С ним сравнивается узел дерева, к которому применяется шаблон. Прежде всего процессору XSL надо сообщить желаемую форму вывода. Узнав ожидаемый формат вывода, процессор начнет исследовать исходный документ с корневого узла.

    Образцы (patterns)

    Прежде чем сделать преобразование дерева документа XML, из него следует выбрать те узлы, которые подвергнутся тому или иному преобразованию, Их можно выбирать по имени, содержимому, атрибутам и другим признакам. Условия отбора узлов задаются образцом (pattern), записанным в виде одного или нескольких выражений языка XPath 2.0. Выражения, содержащиеся в образце, объединяются вертикальной чертой |, означающей, что выбираемый узел должен удовлетворять хотя бы одному выражению образца. Вместо вертикальной черты можно записывать слово union.

    В образце можно записать не всякое выражение XPath, а только путь, каждый шаг которого определяется осью, причем допускаются только три оси: child (по умолчанию), // и attribute. Это означает, что, находясь в каком-то узле, мы можем "увидеть", кроме него самого, только его атрибуты и узлы-потомки. Обратите внимание на то, что явная запись оси descendant-or-self недопустима, применяется только сокращенная запись //. Запись оси attribute:: можно сократить до одной "собачки" @, а текущий узел очень часто обозначается точкой.

    Хотя образец и строится как выражение языка XPath, но его цель - не отобрать последовательность узлов, а проверить соответствие узла данному образцу. Можно сказать, что некоторый узел Node соответствует некоторому образцу pattern тогда и только тогда, когда узел Node принадлежит последовательности узлов - результату вычисления выражения //Pattern. Например, образцу person//street будут соответствовать все узлы из последовательности //person//street, а именно все узлы street, вложенные в узлы-элементы person даже через несколько промежуточных узлов.

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

    Функции id() и key()

    Образец может начинаться с вызова функции id() или функции key(). Единственным аргументом функции id() служит уникальный идентификатор узла, т.е. значение его атрибута типа ID. Например, образцу id(@xref) соответствует узел-элемент, на идентификатор которого ссылается значение атрибута xref. Образцу id(<h12>) соответствует узел-элемент с идентификатором h12, а образцу id(<h12>)//street - его потомки street любого уровня вложенности.

    Функция id(), работающая с атрибутами типа ID, подвержена всем ограничениям этого типа, а именно:

  • у элемента может быть только один атрибут типа ID, значит, можно cссылаться только на этот атрибут, не говоря уже о том, что такой атрибут может вообще отсутствовать:
  • значение атрибута типа ID уникально, значит, нельзя обратиться сразу к нескольким элементам;
  • значение атрибута типа ID может быть только именем типа Name, значит, не может быть числом, содержать пробелы и многие другие символы;
  • схема, в которой определен тип ID атрибута, может оказаться недоступной для процессора XSLT и он не "узнает" тип атрибута;
  • функция id() работает только с атрибутами, но не с элементами, их содержимым и прочими узлами дерева документа;
  • для внесения новых перекрестных ссылок в документ XML надо его менять, вставляя атрибуты типа ID, что может быть нежелательно или невозможно.
  • Функция key() менее требовательна. Она снимает ограничения функции id(), обращаясь не к атрибуту элемента, находящегося в документе ХМL, а к атрибуту use специального элемента xsl:key, расположенного в таблице стилей. У нее два аргумента:

  • имя ключа, задаваемое строкой типа QName; это значение атрибута name элемента xsl:key, позволяющее выбрать нужный элемент xsl:key.
  • значение ключа, представляющее собой выражение, в результате вычисления которого получается последовательность из одного или нескольких атомарных значений типа xdt:anyAtomicType.
  • Образец с функцией key() выглядит примерно так:
    key("addr", 230007)//street.

    Элемент xsl:key определяет ключ и множество значений, а функция key() выбирает из этого множества те значения, что совпадают со вторым аргументом функции key(). Таким образом, при необходимости создания новых ссылок в исходном документе XML, его не надо изменить, достаточно добавить новые элементы xml:key в таблицу стилей.

    Элементы, объявленные в XSLT

    Язык XSLT объявляет около полусотни элементов. Из них 17 элементов верхнего уровня, которые могут быть непосредственно вложены в корневой элемент xsl:stylesheet таблицы стилей. Они называются декларациями. Это элементы xsl: import, xsl: include, xsl: attribute-set, xsl:character-map, xsl:date-format, xsl:decimal-format, xsl:function, xsl:import-schema, xsl:key, xsl:namespace-alias, xsl:output, xsl:param, xsl:preserve-space, xsl:sort-key, xsl:strip-space, xsl:template, xsl:variable. Более того, все эти элементы, кроме xsl:param и xsl: variable, можно записывать только на верхнем уровне вложенности, непосредственно в корневом элементе xsl:stylesheet.

    Кроме элементов верхнего уровня вложенности, в языке XSLT объявлено более тридцати элементов, которые можно записывать в теле элементов верхнего уровня. Наиболее часто применяются элементы xsl:apply-templates, xsl:value-of, xsl:copy-of, xsl:sort, xsl:text.

    Из всех элементов XSLT не верхнего уровня вложенности выделяются инструкции. Не путайте инструкции XSLT и инструкции по обработке XML. Формально инструкции XSLT определяются как элементы, которые можно вставлять в конструктор последовательности. К инструкциям, в частности, относятся элементы, создающие узлы всех семи видов и последовательности узлов. Это элементы xsl:element, xsl:attribute, xsl:text, xsl:comment, xsl:processing-instruction, xsl:namespace, xsl:result-document, xsl:sequence.

    Кроме них, инструкциями считаются элементы xsl:apply-templates, x sl: value-of, xsl: variable и др., всего более двадцати элементов. К инструкциям относятся как элементы, управляющие выбором правил преобразовании xsl:if, xsl:for-each, xsl:choose, так и элементы, копирующие узлы xsl:copy, xsl:copy-of.

    Все элементы необязательны и могут располагаться в любом порядке, за одним исключением: декларации xsl:import, если они есть, должны быть записаны первыми.

    Рассмотрим некоторые наиболее часто применяемые элементы XSLT.

    Декларация xsl:import

    Элемент xsl:import записывается очень просто:

    <хsl:import href="адрес URI таблицы стилей" />

    Его можно записать только непосредственно в корневом элементе xsl:stylesheet и только в самом начале таблицы стилей. Элементов xsl: import может быть несколько.

    Процессор XSLT отыскивает таблицу стилей по указанному атрибутом href адресу и подставляет ее на место элемента xsl:import перед преобразованием.

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

    Декларация xsl:include

    Второй элемент, включающий внешние таблицы стилей в данную таблицу, - это элемент xsl:include. Он записывается точно так же, как элемент xsl:import, и оказывает такое же действие:

    <xsl:include href="адрес URI таблицы стилей" />

    Его можно записать не только непосредственно в корневом элементе xsl:stylesheet, но, в отличие от элемента xsl:import, в любом месте таблицы стилей. Второе отличие от элемента xsl:import заключается в том, что порядок записи элементов xsl:include в таблице стилей не имеет значения.

    Декларация xsl:variable

    Элемент xsl:variable определяет имя объекта. Оно записывается обязательным атрибутом name. Имя объекта должно быть уточненным именем XML типа QName. Кроме того, атрибутом select переменной можно задать сам объект, а атрибутом as определить тип объекта. Например:

    <xsl:variable name="var1" select="count(//person)" as="xs:integer" />

    Имя var1 будет хранить число элементов person. Объект может быть получен из содержимого элемента xsl: variable:

    <xsl: variable name="var2">10</xsl:variable>

    или создан конструктором последовательности:

    <xsl:variable name="var3">
    <xsl:value-of select="count (//person) " /> 
    <xsl:variable>

    Если объект не получен из атрибута select или содержимого элемента xsl: variable, то по умолчанию имя связывается с пустой строкой.

    Для того чтобы получить объект, связанный с именем, определенным элементом xsl: variable, перед именем надо поставить знак доллара: $varl, $var2. При этом следует учитывать область действия имени.

    Область действия имени простирается на весь элемент, в котором оно определено, начиная с места определения и включая вложенные элементы, если только в них не определено то же самое имя.

    Имена, определенные непосредственно в корневом элементе xsl:stylesheet, называются глобальными именами, остальные - локальными именами.

    Хотя слово "variable" и переводится с английского языка как "переменная", имя, созданное элементом xsl: variable - это не имя переменной, его значение нельзя изменить. Это только название некоторого объекта, которое удобно использовать в тех случаях, когда объект надо использовать во многих местах таблицы стилей, а его вычисление сложно или громоздко.

    Декларация xsl:param

    Элемент xsl:param записывается или непосредственно в элементе xsl:stylesheet, чтобы задать параметр преобразования, или в элементе xsl:template, чтобы задать параметр правила, или в элементе xsl:function как аргумент функции. У него один обязательный атрибут name, определяющий имя параметра. Кроме него, часто присутствует необязательный атрибут select, в котором записывается выражение для получения значения параметра:

    <xsl:param name="pl" select="10 + 20" />

    Если атрибут select отсутствует, то значение параметра берется из содержимого элемента, которым может быть конструктор последовательности узлов и атомарных значений:

    <xsl:param name="p2">10</xsl:param>

    Если отсутствует и атрибут select, и содержимое элемента, то параметр получает значение пустой строки.

    Дли получении значения параметра надо записывать его имя со знаком доллара: $p1,$p2. Например:

    <xsl:when test= "$p1=10 ">

    Правила, определяющие область видимости параметров, такие же, как и у имен объектов, определенных декларацией xsl:variable.

    Еще один необязательный атрибут as содержит желательный тип, к которому будет приведено значение параметра.

    Наконец, последний атрибут required, принимающий значения yes или nо (по умолчанию), указывает обязательность параметра. Если параметр обязателен, required="yes", то элемент xsl:param должен быть пустым и не содержать атрибут select. В таком случае он получит определенное значение при вызове функции или элементом xsl:with-param при вызове шаблона.

    Элемент xsl:with-param

    Элемент xsl:with-param ссылается на некоторый параметр, имя которого записано в обязательном атрибуте name. Необязательным атрибутом select можно задать выражение, результат вычисления которого будет новым значением параметра:

    <xsl:with-param name="pl" select="100 * 20" />

    Новое значение можно задать и в содержимом элемента:

    <xsl:with-param name="pl">100</xsl:with-param>

    Элемент xsl:with-param используется только в инструкциях xsl:apply-templates, xsl:apply-imports, xsl:call-template.

    Инструкция xsl:value-of

    Элемент xsl:value-of вычисляет выражение, записанное в его обязательном атрибуте select, и преобразует его в строку. Например, выше мы определили имя объекта var2. Чтобы получить значение объекта var2, надо записать:

    <xsl:value-of select="$var2" /></example>

    Если в результате вычисления выражения получается последовательность, то процессор XSLT версии 1.0 выберет из нее только первый элемент, преобразованный в строку.

    Инструкции управления xsl:if, xsl:for-each, xsl:choose

    Элемент xsl:if запускает конструктор последовательности, содержащийся в его теле, только если истинно выражение, записанное в обязательном и единственном атрибуте test:

    <xsl:if test="$x > $у">
    <xsl:value-of select="$x"/> больше <xsl:value-of select="$y" />
    </xsl:if>

    У элемента xsl:for-each в обязательном и единственном атрибуте select записывается выражение, дающее в результате последовательность. Для каждого члена этой последовательности выполняется конструктор, содержащийся в теле элемента xsl:for-each. В результате получается цикл, выполняющийся столько раз, сколько элементов у последовательности, полученной в результате вычисления выражения атрибута select.

    У элемента xsl:choose нет ни одного атрибута, но в его теле записывается один или несколько элементов xsl: when и один необязательный элемент xsl:otherwise:

    <xsl:choose>
    <xsl:when test="$day=l">Понедельник</xsl:when>
    <xsl when test="$day=2">Bторник</xsl:when>
    <xsl when test="$day=3">Cреда</xsl:when>
    <xsl when test="$day=4">Четверг</xsl:when>
    <xsl when test="$day=5">Пятница</xsl:when>
    <xsl when test="$day=6">Cyббота</xsl:when>
    <xsl when test="$day=7">Воскресенье</xsl:when>
    <xsl otherwise>Ошибка определения дня нeдeли</xsl:otherwise>
    </xsl:choose>

    У элемента xsl:when есть только один обязательный параметр test, содержащий логическое выражение, и тело, содержащее конструктор последовательности.

    Элемент xsl: otherwise не имеет атрибутов, у него есть только тело, содержащее конструктор последовательности.

    В инструкции xsl: choose всегда выполняется не больше одного варианта, Варианты xsl:when просматриваются в порядке их написания в инструкции xsl:choose. Как только будет найден вариант с истинным значением выражения test, он будет выполнен, и результат этого варианта будет результатом всей инструкции. Варианты, следующие за ним по порядку, не рассматриваются. Если ни один вариант не подойдет, то результатом инструкции будет результат конструктора, записанного в элементе xsl:otherwise. Если элемента xsl:otherwise в инструкции нет, то результатом будет пустая строка.

    Декларация xsl:function

    Элемент xsl:function позволяет описывать самые настоящие пользовательские функции. Имя функции записывается в обязательном атрибуте nаmе, (аргументы функции задаются элементами xsl:param, а тело функции - это конструктор последовательности, записанный в содержимом элементе xsl:function. Результатом функции будет последовательность, созданная конструктором. Тип функции можно указать необязательным атрибутом аs.

    Имя функции - это уточненное имя типа QName, причем оно должно обязательно записываться с префиксом.

    Все аргументы функции позиционные, следовательно, все элементы xsl:param должны быть записаны в начале тела функции и порядок их записи имеет значение при вызове функции. У аргументов функции не может быть значений по умолчанию, следовательно, элементы xsl:param должны быть пустыми и у них не должно быть атрибутов select. Например:

    <xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:usr="http://myexamples.com"
    xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xsl: function name= " usr:sum "  as="xsl:integer">
    <xsl:param name="x" as="xsl:integer" />
    <xsl:param name="y" as="xsl:integer" />
    <xsl:value-of select="$x + $y" /> 
    </xsl:function>

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

    <хsl:value-of select="10 + 2 * usr:sum(2, 3)" />

    Функция может вызываться рекурсивно.

    Декларация xsl:template

    Элемент xsl:template определяет шаблонное правило преобразования. Своим атрибутом match он задает образец для отбора узлов, подлежащих преобразованию, а в теле содержит конструктор последовательности узлов и атомарных значений, которая и будет результатом преобразования отобранных по образцу узлов.

    <xsl: template match=" Образец" name="Имя">Конструктор</хsl:template>

    Каждый из атрибутов match и name не обязателен, но хотя бы один из них должен присутствовать.

    Атрибут match содержит образец для отбора преобразуемых узлов.

    Атрибут name определяет имя шаблона. Имя шаблона - это обычное уточненное имя XML типа QName. Шаблон можно вызвать по имени элементом xsl:call-template, а если он не содержит атрибута match, то такой вызов обязателен, поскольку неизвестны узлы, к которым его надо применить, и он не будут применяться автоматически. Очень часто именованный шаблон содержит параметры, заданные элементами xsl:param, и вызывается с различными параметрами совсем как обычная функция.

    У элемента xsl: template могут быть дополнительные атрибуты mode, as, priority.

    Атрибут mode определяет режим обработки.

    Атрибут as указывает желаемый тип результата (полученная последовательность будет приведена к этому типу).

    Атрибут priority назначает правилу приоритет, который будет учитываться при отборе правил, применимых к некоторому узлу.

    При вызове именованного шаблона элементов xsl:call-template атрибуты match, mode и priority игнорируются.

    Если у именованного шаблона нет атрибута match, то у него не должно быть и атрибутов mode и priority, в них просто нет никакого смысла.

    Инструкция xsl:apply-templates

    Элемент xsl:apply-templates, записываемый чаще всего внутри элемента xsl: template, в простейшем виде пуст:

    <xsl:apply-templates />

    Он предписывает обработать рекурсивно все узлы-потомки узлов, отобранных родительским элементом xsl:template.

    У элемента xsl:apply-templates есть необязательные атрибуты select и mode.

    Атрибут select, значением которого должно быть выражение, дающее последовательность узлов, ограничивает обработку только указанными в нем узлами.

    Атрибут mode выбирает режим обработки из режимов, уже определенных в элементах xsl:template. Режим - это любое имя типа QName, но два режима предопределены. Это текущий режим, отмечаемый словом #current, и режим по умолчанию, принимаемый при отсутствии атрибута mode, или отмечаемый явно словом #default.

    Содержимым элемента xsl: apply-templates могут служить элементы xsl:sort и xsl:with-param.

    Инструкция xsl:for-each-group

    Элемент xsl:for-each-group отбирает последовательность узлов и атомарных значений своим обязательным атрибутом select и группирует ее элементы по признаку, заданному выражением, записанным в атрибуте group-by. Этот признак называется ключом группы. Ключ группы вычисляется заново для каждого элемента последовательности. В результате исходная последовательность, отобранная атрибутом select, разбивается на несколько последовательностей. В следующем примере в одну группу собираются все узлы-элементы name с одинаковым значением атрибута surname:

    <xsl:for-each-group select="name" group-by="@surname">

    Выражение, являющееся значением атрибута group-by, может давать несколько ключей группы, и один узел может попасть сразу в несколько групп. Например:

    <xsl:for-each-group select="name" group-by="(@second, @surname)">

    Второй способ разбить последовательность на группы дает атрибут group-adjacent. Он собирает в группу все подряд идущие элементы последовательности с одинаковым значением ключа. Такой отбор возможен, если в атрибуте group-adjacent содержится только один ключ группы. Процессор XSLT следит за тем, чтобы значением атрибута group-adjacent был один и только один ключ группы.

    Третий и четвертый способы применимы к последовательностям, состоящим только из узлов, без атомарных значений. Эти способы применяют атрибут group-starting-with или атрибут group-ending-with. Значением этих атрибутов может быть не любое выражение, а только образец. В одну группу собираются все подряд идущие узлы, первый (последний) из которых удовлетворяет образцу. Остальные узлы из этой группы не будут удовлетворять образцу. Если несколько подряд идущих элементов последовательности удовлетворяют образцу, то они попадут в разные группы.

    Итак, группы узлов создаются одним из четырех атрибутов элемента xsl:for-each-group: group-by, group-adjacent, group-starting-with, group-ending-with. В каждом элементе xsl:for-each-group должен быть один и только один из этих атрибутов. Полученные группы существуют и могут использоваться только в содержимом элемента xsl:for-each-group. В теле элемента xsl:for-each-group записывается конструктор последовательности, который выполняется по одному разу для каждой группы.

    Для удобства работы с группами в язык XSLT введены функции current-group() и current-group-key ().Их можно использовать только в теле элемента xsl:for-each-group. У обеих функций нет аргументов. Результатом функции current-group() будет последовательность- текущая группа, а результатом функции current-group-key() - значение ключа текущей группы.

    Функции процессора XSL

  • Во-первых, процессор строит рощу, являющуюся внутренним представлением документа. Эта роща всегда имеет корневой элемент, представляющий собой весь документ XML, а не его элемент верхнего уровня. Ниже корневого элемента расположена вся иерархия узлов. Каждый узел типизирован. Например, он может быть предназначен для определения DTD, для схемы или для команды обработки. Если элемент содержит атрибуты, то у каждого элемента также имеется коллекция узлов атрибутов. Если элемент содержит данные, то в узел элемента вкладывается еще и соответствующие им узел. Таким образом, потомками узла элемента может быть коллекция узлов атрибутов и узел данных.
  • Во-вторых, создает структуру для документа XSLT. Она также может представлять собой рощу, но может быть структурой любого типа, оптимизированной для обработки шаблонов и соответствия образцов.
  • Затем каждый раз, встретив элемент <xsl: apply-templates>, формирует список узлов и продолжит работу с этим списком. Если элемент <xsl:apply-templates> содержит атрибут select, список узлов формируется на основе указанного запроса XPath. В противном случае список содержит все дочерние узлы.
  • Каждый раз, встретив конструкцию <xsl: value-of>, процессор извлекает значение из исходного дерева, основываясь на выражении XPath ее атрибута select.
  • Трансформация не ограничивается только трансляцией типа один-к-одному: она позволяет добавлять новое информационное содержание, добавлять и удалять элементы, а также осуществлять трансляции типа один-ко-многим.
  • Трансформация документа XML с помощью модели DOM

    Документ XML можно трансформировать и с помощью модели DOM, являющейся интерфейсом для представления документа в виде дерева. Однако такой способ трансформации документа является несколько рискованным, поскольку большинство реализации DOM содержит множество частных, свойственных только им конструкций. Например, даже в рекомендациях по DOM 2 не указано, каким образом загружать или сохранять документы XML, поэтому те, кто занимается их реализацией, должны изобретать свои методы для этих фундаментальных операций. В результате большинство сценариев, используемых для трансформации документов XML, не будут переносимыми, поскольку, как правило, содержат различные частные конструкции

    Вернуться к учебному плану