КаталогИндекс раздела


Что за язык XSLT?
Анализ и обзор

Michael Kay
01 февраля 2001, обновлено 20 апреля 2005

© ibm.deweloperworks
© А.С.Деревянко (перевод)

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

Я изначально писал эту статью, чтобы создать необходимую основу для технической статьи о Saxon, предназначенной обеспечить понимание приемов реализации, используемых в типичном процессоре XSLT и, следовательно, помочь пользователям максимизировать производительность их таблиц стилей. Но редакционная команда developerWorks убедила меня, что это введение должно быть интересным для гораздо более широкой аудитории и что стоит его опубликовать отдельно, как самостоятельное описание языка XSLT.

Что такое XSLT?

Язык XSLT был определен World Wide Web Consortium (W3C), и версия языка 1.0 была опубликована как Рекомендация 16 ноября 1999 г. (см. Ресурсы). Я представил полную спецификацию языка и руководство пользователя в моей книге XSLT Programmers' Reference, и я не намерен в этой статье повторяться. Вместо этого, моей целью является просто дать понимание того, какое место занимает XSLT в общей укрупненной схеме.

Роль XSLT

XSLT произошел от стремления отделить содержание информации от презентации в Web. HTML, как он был определен исходно, достигает определенной степени независимости от устройств путем определения презентации в абстрактных терминах, таких как параграфы, выделения и нумерованные списки. По мере того, как Web становится все более коммерческим, публикаторы хотят такого же контроля над качеством выводимой информации, какой они имеют на печатных носителях. Это постепенно приводит к увеличению использования конкретных управляющих элементов презентации, таких как явно задаваемый шрифт и абсолютная позиция материала на странице. Плачевным, но вполне предсказуемым побочным эффектом является то, что становится все труднее распространять одно и то же содержимое на альтернативные устройства, такие как цифровые TV и WAP-телефоны (повторно использовать [repurposing] на профессиональном жаргоне публикаторов).

Руководствуясь опытом SGML в мире печатных публикаций, XML был определен ранее в 1998 как язык разметки для представления структурированного содержимого независимо от его презентации. В отличие от HTML, который использует фиксированный набор концепций (таких как параграфы, списки и таблицы), теги, используемые в разметке XML, полностью определяются пользователем, и смысл состоит в том, что они должны относиться к объектам из области его интересов (таким как люди, места, цены, даты). В то время как элементы HTML в значительной степени типографские (хотя и на определенном уровне абстракции), цель XML состоит в том, что элементы должны описывать объекты реального мира. Например, листинг 1 показывает XML-документ, представляющий результаты футбольного турнира.

Листинг 1. XML-документ, представляющий результаты футбольного турнира

      <results group="A">
      <match>
          <date>10-Jun-1998</date>
          <team score="2">Brazil</team>
          <team score="1">Scotland</team>      
      </match>
      <match>
          <date>10-Jun-1998</date>
          <team score="2">Morocco</team>
          <team score="2">Norway</team>
      </match>
      <match>
          <date>16-Jun-1998</date>
          <team score="1">Scotland</team>
          <team score="1">Norway</team>
      </match>
      <match>
          <date>16-Jun-1998</date>
          <team score="3">Brazil</team>
          <team score="0">Morocco</team>
      </match>
      <match>
          <date>23-Jun-1998</date>
          <team score="1">Brazil</team>
          <team score="2">Norway</team>
      </match>
      <match>
          <date>23-Jun-1998</date>
          <team score="0">Scotland</team>
          <team score="3">Morocco</team>
      </match>
      </results>

Если вы хотите отобразить эти футбольные результаты через Web-браузер, вы не можете надеяться, что вам попадется система с подходящей экранной раскладкой. Нужны некоторые другие механизмы, чтобы сообщить системе, как отображать данные на экране браузера, на TV-приемнике, на WAP-телефоне и, конечно, на бумаге. Вот здесь появляется таблица стилей. Таблица стилей - это декларативный набор правил, который определяет, как информационные элементы, идентифицируемые тегами в исходном документе, должны изображаться.

W3C определил два семейства стандартов для таблиц стилей. Первое, известное как CSS (Cascading Style Sheets), широко применяется с HTML, хотя оно может использоваться и с XML. CSS могут применяться, например, чтобы сообщить, что при отображении счета общая сумма платежа должна быть показана шрифтом Helvetica, 16 пунктов, полужирным. Однако CSS не имеет возможности выполнять вычисления, переупорядочивать или сортировать данные, комбинировать данные из разных источников или персонализировать отображаемое в соответствии с характеристиками пользователя или сеанса. В случае наших футбольных результатов, CSS (даже их последняя версия, CSS2, которая еще не полностью реализована в продуктах) не является достаточно мощным языком, чтобы справиться с этой задачей. По этим причинам W3C инициировал разработку более богатого языка таблиц стилей, который стал известен как XSL (Extensible Stylesheet Language), воспринявшего многие идеи из DSSSL (Document Style, Semantics, and Specification Language), разработанного в сообществе SGML.

В ходе разработки XSL (как это было предсказано в DSSSL), выяснилось, что задачи, выполняемые в подготовке XML-документа к отображению, могут быть разбиты на два этапа: трансформация и форматирование. Трансформация - это процесс преобразования одного XML-документа (или его представления в памяти) в другой. Форматирование - это процесс преобразования трансформированной структуры дерева в двумерное графическое представление или, возможно, в одномерный аудио-поток. XSLT был разработан как язык для управления первым этапом, трансформацией. Разработка для второго этапа, форматирования, все еще продолжается. Но на практике большинство людей сейчас использует XSLT для трансформации XML-документов в HTML и использует браузер HTML как движок форматирования. Это возможно потому, что для всех предназначений и целей HTML является только одним примером словаря XML, а XSLT способен использовать любой словарь XML как целевой.

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

В моей книге я предположил, что XSLT является для XML тем, чем SQL является для табличных данных. Реляционная модель получает свою мощность не от идеи хранения данных в таблицах, а от высокоуровневого манипулирования данными, возможного в SQL на основе реляционного исчисления. Аналогично, иерархическая модель данных XML сама по себе мало чем помогает разработчикам приложений. Именно XSLT как высокоуровневый язык манипулирования данными XML обеспечивает мощность.

XSLT как язык

Как язык, XSLT в некоторых отношениях является необычным зверем. В этой статье я не буду пытаться давать объяснения принятым проектным решениям, хотя они все могут быть логически прослежены от требований, которые установили разработчики языка. Более комплексное описание см. в Главе 1 моей книги.

Некоторые ключевые свойства языка XSLT очерчены ниже.

Таблица стилей XSLT является XML-документом. Структура документа представляется с использованием синтаксиса тегов в угловых скобках XML. В некотором отношении этот синтаксис несколько нескладный, и решение делает язык несколько многословным. Это имеет, однако, свои преимущества. Это означает, что весь лексический аппарат XML (например, символьная кодировка Unicode и escape-символы, использование внешних сущностей и т.п.) доступен автоматически. Это означает, что легко сделать таблицу стилей XSLT входом или выходом трансформации, что дает языку возможности замкнутости. Это также делает его легким для встраивания фрагментов требуемого XML-выхода в таблицу стилей. Фактически, многие простые таблицы стилей могут быть написаны по существу как шаблоны для требуемого выходного документа с редкими встроенными в текст инструкциями для вставки переменных данных из входа или вычисления значений. Это делает XSLT, на этом простом уровне, очень похожим на многие существующие языки шаблонов HTML.

Основной парадигмой обработки является соответствие образцам. В этом отношении XSLT следует давней традиции таких языков обработки текстов как Perl, традиции, которая прослеживается от таких языков, как SNOBOL в 1960-е. Таблица стилей XSLT состоит из ряда шаблонных правил, каждое из которых имеет форму "если такое-то условие встречается на входе, то генерировать такой-то выход". Порядок правил несущественен, и имеется алгоритм разрешения конфликтов, который применяется, если несколько правил применимы для одного входа. В одном отношении, однако, XSLT отличается от большинства языков обработки текстов, это то, что вход не обрабатывается последовательно, строка за строкой. Вместо этого входной XML-документ рассматривается как структура дерева, и каждое шаблонное правило применяется к узлу дерева. Шаблонное правило может само решать, какой узел должен обрабатываться следующим, так что вход не обязательно сканируется в оригинальном порядке документа.

Работа процессора XSLT

Процессор XSLT принимает на входе структуру дерева и генерирует на выходе другую структуру дерева. Это показано на Рисунке 1.

Рисунок 1. Работа процессора XSLT

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

XSLT использует подъязык, называемый XPath, чтобы обращаться к узлам входного дерева. XPath - это, по существу, язык запросов, соответствующий иерархической модели данных XML. Он способен выбирать узлы навигацией по дереву в любом направлении и применять предикаты, базирующиеся на значении и позиции узла. Он также включает в себя основные операции манипулирования строками, числовых вычислений и Булевой алгебры. Например, выражение XPath ../@title выбирает атрибут title элемента, который является предком текущего узла. Выражения XPath используются для выборки входных узлов для обработки, для проверки условий при условной обработке и для вычисления значений для вставки в результирующее дерево. Простейшая форма выражения XPath, образец, также используется в шаблонных правилах для определения того, к каким узлам применимо данное шаблонное правило. XPath определен как отдельная Рекомендация W3C, чтобы язык запросов мог использоваться в другом контексте, в особенности, в синтаксисе XPointer для определения расширенных гиперссылок.

XSLT базируется на концепции функционального программирования в традициях таких языков, как Lisp, Haskell и Scheme. Таблица стилей составляется из шаблонов, которые, в сущности, являются просто функциями - каждый шаблон определяет фрагмент выходного дерева как функцию фрагмента входного дерева и не создает побочных эффектов. Правило "без побочных эффектов" применяется очень строго (за исключением переходов во внешний код, написанный на таком языке, как Java). Язык XSLT разрешает определять переменные, но не разрешает менять значение существующей переменной - в языке нет оператора присваивания. Причина такой политики, которая многих новых пользователей приводит в замешательство, состоит в возможности инкрементного применения таблиц стилей. Теория этого состоит в том, что, если язык свободен от побочных эффектов, то при малом изменении во входном документе имеется возможность вычислить результирующее изменение в выходном документе, не выполняя всю трансформацию в полном объеме. Следует сказать, что на данный момент это остается теоретической возможностью, которая не достигнута в существующих процессорах XSLT. (Примечание: Хотя XSLT базируется на идеях функционального программирования, он еще не является полностью языком функционального программирования, в нем недостает возможности трактовать функции как тип данных.)

Пример таблицы стилей

На этом этапе язык станет более ясным для нас через пример. Листинг 2 показывает простую таблицу стилей для перечисления футбольных результатов.

Листинг 2. Базовая таблица стилей для футбольных результатов

      <xsl:transform
          xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
      <xsl:template match="results">
          <html>
          <head><title>
              Results of Group <xsl:value-of select="@group"/>
          </title></head>
          <body><h1>
              Results of Group <xsl:value-of select="@group"/>
          </h1>
          <xsl:apply-templates/>
          </body></html>
      </xsl:template>
      <xsl:template match="match">
          <h2>
              <xsl:value-of select="team[1]"/> versus <xsl:value-of select="team[2]"/>      
          </h2>
          <p>Played on <xsl:value-of select="date"/></p>
          <p>Result: 
                  <xsl:value-of select="team[1] "/> 
                  <xsl:value-of select="team[1]/@score"/>,
                  <xsl:value-of select="team[2] "/> 
                  <xsl:value-of select="team[2]/@score"/>
          </p>
      </xsl:template>
      </xsl:transform> 

Эта таблица стилей состоит из двух шаблонных правил, одно на соответствие элементу <results>, другое на соответствие элементу <match> (извините за омоним [match - соответствовать и match - матч - прим. перев.]). Шаблонное правило для элемента <results> выдает заголовок HTML для страницы, а затем вызывает <xsl:apply-templates/>, являющуюся инструкцией XSLT, которая приводит к обработке всех дочерних узлов текущего элемента, каждого - с использованием его определенных шаблонных правил. В данном случае все дочерние узлы элемента <results> являются элементами <match>, так что все они обрабатываются с использованием второго шаблонного правила. Правило выводит заголовок HTML второго уровня, идентифицирующий матч (в форме "Brazil versus Scotland"), а затем генерирует параграфы HTML с датой матча и счетом для обеих команд.

Результатом этой трансформации является HTML-документ, который изображается в браузере, как показано на Рисунке 2.

Рисунок 2. Результат таблицы стилей из Листинга 2

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

Листинг 3. Таблица стилей, которая вычисляет положения команд

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

      <xsl:variable name="teams" select="//team[not(.=preceding::team)]"/>
      <xsl:variable name="matches" select="//match"/>

      <xsl:template match="results">

      <html><body>
         <h1>Results of Group <xsl:value-of select="@group"/></h1>

         <table cellpadding="5">
            <tr>
              <td>Team</td>
              <td>Played</td>
              <td>Won</td>
              <td>Drawn</td>
              <td>Lost</td>
              <td>For</td>
              <td>Against</td>
            </tr>
         <xsl:for-each select="$teams">
              <xsl:variable name="this" select="."/>
              <xsl:variable name="played" select="count($matches[team=$this])"/>

              <xsl:variable name="won" 
                  select="count($matches[team[.=$this]/@score > team[.!=$this]/@score])"/>
              <xsl:variable name="lost"
                  select="count($matches[team[.=$this]/@score < team[.!=$this]/@score])"/>      
              <xsl:variable name="drawn"
                  select="count($matches[team[.=$this]/@score = team[.!=$this]/@score])"/>
              <xsl:variable name="for"
                  select="sum($matches/team[.=current()]/@score)"/>
              <xsl:variable name="against"
                  select="sum($matches[team=current()]/team/@score) - $for"/>

              <tr>
              <td><xsl:value-of select="."/></td>
              <td><xsl:value-of select="$played"/></td>
              <td><xsl:value-of select="$won"/></td>
              <td><xsl:value-of select="$drawn"/></td>
              <td><xsl:value-of select="$lost"/></td>
              <td><xsl:value-of select="$for"/></td>
              <td><xsl:value-of select="$against"/></td>
              </tr>
         </xsl:for-each>
         </table>
      </body></html>
      </xsl:template>

      </xsl:transform> 

Здесь нет места для полного объяснения этой таблицы стилей, но в итоге она объявляет переменную для команд, значением которой является набор узлов, содержащий по одному экземпляру каждой команды, участвующей в турнире. Затем для каждой из этих команд вычисляется общее число матчей, число матчей выигранных, ничейных и проигранных и число забитых и число пропущенных голов. Рисунок 3 показывает результат в браузере.

Рисунок 3. Результат таблицы стилей из Листинга 3

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

Преимущества XSLT

Почему вам стоит подумать об использовании XSLT?

XSLT дает вам все традиционные преимущества высокоуровневого декларативного языка программирования, специализированного для задач трансформации XML-документов.

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

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

Резюме

Я старался показать в этой статье, что XSLT является законченным высокоуровневым языком программирования для манипулирования XML-документами так же, как SQL является высокоуровневым языком для манипулирования реляционными таблицами. Важно понимать, что он значительно больше, чем просто язык стилей, и что он намного мощнее, чем CSS (или даже CSS2).

Я уже видел приложения, в которых вся бизнес-логика кодирована в XSLT. В одной трехуровневой онлайновой банковской системе я увидал, что:

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

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

Постскриптум

Michael Kay написал в апреле 2005 г.: Хотя эта статья была написана четыре года назад, она выдержала испытание временем. Конечно, XSLT 2.0 значительно изменил картину, но опять перечитывая статью, я не нахожу необходимости ее изменять: Новые свойства в 2.0 не меняют фундаментальных концепций языка, описанных здесь.

Ресурсы

Об авторе

Michael Kay написал эту статью вскоре после того, как он оставил ICL, где он потратил 24 года на разработку Codasyl и программного обеспечения для реляционных, объектно-ориентированных и полнотекстовых бах данных. Затем он проработал в Software AG три года, большая часть которых была посвящена работе со стандартами в W3C в качестве редактора спецификации XSLT 2.. Сейчас он создал собственную компанию, Saxonica, которая продолжает разработку продукта Saxon и обеспечивает соответствующий сервис. Между делом, он выпустил новые редакции книг в издательстве Wrox XSLT 2.0 Programmer's Reference и XPath 2.0 Programmer's Reference. Автор выбрал эту фотографию, чтобы показать, что он не всегда такой серьезный, как он выглядит на обложках книг издательства Wrox.


КаталогИндекс раздела