Алексей Валиков - Технология XSLT
<pre>One little rabbit<BR/>
Two little rabbits<BR/>
Three little rabbits</pre>
Данные, разделенные запятыми (CSV)
Рекурсивную методику замены, которую мы представили выше, можно использовать для того, чтобы разметить данные, разделенные запятыми (или CSV, comma-separated values). CSV — это старый простой формат представления данных, в котором они просто перечисляются через запятую, например:
a, b, с, d, e, f, g
и так далее. Формат CSV был одним из первых шагов к созданию языков разметки: данные в нем уже размечались запятыми.
Покажем на простом примере, как можно преобразовать CSV-данные в XML-документ. Пусть входящий документ выглядит как:
<data>a, b, с, d, e, f</data>
Для того чтобы решение было как можно более общим, вынесем создание XML-разметки для каждого из элементов этой последовательности в отдельный шаблон:
<xsl:template name="item">
<xsl:param name="item"/>
<item><xsl:copy-of select="$item"/></item>
</xsl:template>
Тогда головной размечающий шаблон запишется в виде.
Листинг 11.18. Шаблон, размечающий данные в строковом формате<xsl:template name="markup" match="text()" mode="CSV">
<xsl:param name="str" select="."/>
<xsl:param name="delimiter" select="','"/>
<xsl:choose>
<xsl:when test="contains($str,$delimiter)">
<xsl:call-template name="item">
<xsl:with-param name="item"
select="substring-before($str, $delimiter)"/>
</xsl:call-template>
<xsl:call-template name="markup">
<xsl:with-param name="str"
select="substring-after($str, $delimiter)"/>
</xsl:call-template>
<xsl:with-param name="delimiter" select="$delimiter"/>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="item">
<xsl:with-param name="item" select="$str"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
На вход шаблон markup принимает два параметра — str, строка, которую нужно разметить (по умолчанию — значение текущего узла) и delimiter — строка, разделяющая отдельные значения в str (по умолчанию — запятая ",").
Шаблон, форматирующий содержимое элемента data, будет в таком случае выглядеть следующим образом:
<xsl:template match="data">
<xsl:copy>
<xsl:apply-templates mode="CSV"/>
</xsl:copy>
</xsl:template>
Результат этого преобразования будет иметь следующий вид:
<data>
<item>a</item>
<item> b</item>
<item> c</item>
<item> d</item>
<item> e</item>
<item> f</item>
</data>
Обратим внимание на то, что в элементах item присутствуют лишние пробелы, которые в начальной последовательности шли за запятыми. Избавиться от них можно, указав в качестве разделяющей строки символ ", ":
<xsl:template match="data">
<xsl:copy>
<xsl:apply-templates mode="CSV">
<xsl:with-param name="delimiter" select="', '"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
Результатом, как и следовало ожидать, будет:
<data>
<item>a</item>
<item>b</item>
<item>c</item>
<item>d</item>
<item>e</item>
<item>f</item>
</data>
Кстати сказать, того же эффекта можно было добиться, изменив шаблон item, который отвечает за XML-представление каждого из элементов последовательности.
Глава 12
Развитие технологий
Как известно, успех технологии зависит не только от того, насколько продумана и проработана она была. Ее широкое распространение невозможно без поддержки и заинтересованности ведущих производителей программного обеспечения. В этом смысле XSLT очень повезло: имплементациями языка с самых ранних черновых вариантов занимались такие крупные разработчики, как Microsoft, Oracle, IBM, Adobe, Lotus и многие другие. Поддержка Apache XML Project помогла XSLT завоевать популярность и среди open-source сообщества (open-source — разработки с "открытым" исходным кодом).
Так или иначе, сейчас следует лишь констатировать стабильный рост популярности XSLT. Количество XSLT-процессоров уже исчисляется десятками, а число разработчиков — пожалуй, что и тысячами.
Повышенный интерес помог в чрезвычайно короткий срок (менее года) изучить на практике недостатки и достоинства нового языка и приступить к разработке последующих версий, которые бы учитывали эти практические результаты. В декабре 2000 года была выпущена версия 1.1,. в которой было не только исправлено большинство основных проблем первой версии XSLT, но и включены очень важные дополнения — такие, например, как определение интерфейсов расширений для языков Java и JavaScript/ECMAScript. В августе 2001 года версии 1.1 дали статус Final Draft и положили на полку — она никогда не будет стандартом (технической рекомендацией Консорциума W3).
Нужно сказать, что по количеству доработок и дополнений версия XSLT 1.1 могла вполне претендовать на роль нового стандарта XSLT. Однако, в такой напряженной области информационных технологий, как XML, приходится считаться с другими разработками, ибо все они взаимосвязаны. На решение прекратить продвижение XSLT 1.1 и перейти к 2.0 во многом повлияли такие проекты, как XML Schema и XQuery.
XML Schema — это долгожданный XML-язык, описывающий структуру XML-документа, своего рода более мощный вариант DTD. XML Schema, в частности, позволяет описывать простые и сложные типы данных элементов и атрибутов, ограничивать количества повторений, определять в XML-документах первичные и внешние ключи и многое другое. Помимо этого, XML Schema определяется в XML-синтаксисе, что позволяет использовать для обработки схем стандартные XML-инструменты. Спецификация XML Schema получила статус технической рекомендации Консорциума W3 в мае 2001 года.
XQuery — это текущий проект W3C по созданию языка запросов для XML-документов. В основу XQuery легло множество предыдущих исследований в области языков запросов для полуструктурированных данных — пожалуй, стоит упомянуть такие, как Quilt, XML-QL и Lorel. Почти все старые языки запросов для XML были университетскими исследовательскими проектами; в XQuery же заинтересованы такие гиганты, как Microsoft и Software AG.
Следует пояснить, каким образом XML Schema и XQuery влияют на XSLT — казалось бы, их области применения несколько различаются. Напомним, что весомая часть функциональности XSLT зависит от языка XPath, который используется также и в XPointer. Как оказалось, XPath важен не только для XSLT и XPointer, но и для XQuery. Модель XML-документа, описанная в первой версии XPath, оказалась мощной, легко реализуемой и понятной абстракцией физической сущности XML и поэтому ее было решено использовать также и в XQuery. В следующей своей инкарнации эта модель будет выделена в отдельную спецификацию — "XQuery 1.0 and XPath 2.0 Data Model" ("Модель данных XQuery 1.0 и XPath 2.0"). Функции и операторы также будут выделены в отдельный документ — "XQuery 1.0 and XPath 2.0 Functions and Operators Version 1.0" ("Операторы и функции в XQuery 1.0 и XPath 2.0, версия 1.0").
Принятие XML Schema также оказывает определенное влияние на XPath. В схемах ХМL-документов можно определять типы данных атрибутов и элементов. Соответственно, семантика XPath выражений должна отражать эту метаинформацию: например, оператор сложения "+" будет вести себя по-разному на строковых и числовых операндах.
ПримерРассмотрим выражение int/x + int/y на простейшем документе:
<int>
<x>2</x>
<y>2</y>
</int>
В первой версии XPath результатом вычисления int/x + int/у в любом случае будет 4. Между тем, старшие версии могут учитывать метаинформацию о типе обрабатываемых данных и возвращать 4 в случае числовых операндов и "22" в случае строковых.
На момент написания этих строк работа над XSLT 2.0 и XPath 2.0 идет полным ходом. Конечно, пока еще рано заглядывать вперед и раскрывать секреты рабочей группы XSL, однако, основываясь на опубликованных спецификациях XLST 1.1 и требованиях к версии XSLT 2.0, кое-какие выводы сделать все же можно.
Отличия XSLT 1.1 от XSLT 1.0
Отсутствие result tree fragment
Главное и наиболее существенное отличие XSLT 1.1 от XSLT 1.0 состоит в том, что тип данных, известный в XSLT 1.0 как result tree fragment (результирующий фрагмент дерева) в XSLT 1.1. отсутствует. Вместо него в версии 1.1 используется множество узлов, состоящее из единственного корневого узла результирующего фрагмента.
На первый взгляд, разница между двумя этими методами представления фрагментов деревьев минимальна. Но если принять во внимание положения языка XPath о том, что ни один тип данных не может быть преобразован во множество узлов, разница эта оказывается огромной. Получается, что, несмотря на то, что результирующий фрагмент и множество, состоящее из его корня, представляют одни и те же данные и структуры, с фрагментом нельзя делать многое из того, что можно делать с множеством узлов.