Консалтинг и автоматизация в области управления
эффективностью банковского бизнеса

Журнал ВРМ World

Будущее XSTL 2.0

Недавно я написал в своем блоге заметку о том, каким вижу направление дальнейшего развития ХML. Заметка оказалась весьма популярной и вызвала немало комментариев, которые не худо бы разобрать как следует. Один из них (на него я ответил бы по любому) касается моего утверждения о том, что XSLT 2.0 все чаще используется как, маршрутизатор, вытесняя такие приложения, как Microsoft BizTalk Server.

Пожалуй, по мере того, как в мире все чаще предпочитают ХML в качестве средства транспорта данных, другие технологии, вроде ХSLT 2.0, скорее всего в целом утратят свою функциональную избыточность, полезную преимущественно "для больших оказий". Сегодня большинство баз данных, так или иначе - напрямую с помощью специальных файловых расширений или посредством слоя XQuery - генерируют ХML. Собственно БД все менее присуще абстрагирование данных, что с точки зрения внешнего приложения означает просто еще один вектор предоставления ХML в заданном формате (в свою очередь, и все в большей степени для загрузки передаваемого ХML).

SQL не очень-то четок при преобразовании контента. Разработчики же, не упустили случая с выгодой для себя воспользоваться этим, предоставляя для доступа к таким БД свой собственный прикладной интерфейс (API). Поэтому, даже применительно к MySQL, первичный формат преобразования, по большей части, это либо явный упаковщик API, либо текстовый вывод, зависящий от поставщика. Это привело к тому, что возникла целая отрасль для почти исключительно "перевода" между SQL выводом/вводом и неким формальным уровнем представления. Можно спорить, что ХSLT сам по себе всего лишь еще один пример слоя преобразования, но, честно говоря, если язык и применяется ненадлежащим образом, само по себе это наблюдение - сущая правда.

Однако в XSLT есть функция, меняющая саму парадигму, под названием document(), а также другая интересная возможность - параметры. Функция document работает не только со статическим ХML контентом, но и способна использовать GET протокол (посредством параметров запроса [query strings]) для поиска контента с помощью веб-сервисов. Параметры могут быть установлены из языка хостинга, и они обусловливают запуск упомянутых сервисов, и вдобавок, их можно высчитать в рамках ХSLT и передать таким же образом.

Заметим, что такой подход таит в себе некоторые проблемы. Начинающие, создавая параметры запроса вначале (с дальнейшей их передачей), страдают от необходимости использовать весьма громоздкий call-template синтаксис, выражать результаты в переменной величине, и только после этого передавать переменную в document() функцию. Есть несколько способов проверки наличия ошибок, а значит, раз созданный вывод невозможно по необходимости использовать как ввод для какой-нибудь другой задачи. Все потому, что вывод - скорее фрагмент ХML, нежели ХML узел.

А значит, хотя и есть определенная возможность такого применения ХSLT, слишком часто приходится полагаться на несовместимые расширения, вроде node-set() функции. Вот и выходит, что большинство интересных вещей, которые может ХSLT 1.0, сводится к этим упорно повторяющимся расширениям. Отсюда снова вопрос: а много ли проку в использовании ХSLT 1.0 с самого начала?

Важные особенности новой версии

Однако, немало, если не большинство проблем просто улетучиваются с ХSLT 2.0, который, на мой взгляд, значительно превосходит прежнюю версию. Вот некоторые новинки:
  • xsl:function . Этот элемент позволяет создавать ХSLT функции, которые можно размещать в специальных пространствах имен и вызывать из выражений XPath, что куда как облегчает создание функциональных моделей с целью превратить ХSLT в формальный язык программирования.
  • Формальный механизм расширений XPath. Теперь у ХSLT есть формальное (и непротиворечивое) средство запуска методов, написанных на иных языках, , из ХSLT-выражений.
  • unparsed-text() и unparsed-text-available() . Метод unparsed-text-available() решает одну из главных проблем при работе с document() - ситуациями, когда URL не может извлечь контент путем проверки правильности URL, чтобы удостовериться: а можно ли по нему извлечь хоть что-нибудь.
  • unparsed-text() . Так решается другая проблема: загрузка контента, отличного от ХML, в ХSLT преобразование. Функция работает на любом контенте, содержащем хоть двоичный код, хоть текстовую информацию. Веб-сервис SOAP передает большие объемы в заголовках, и этот контент необходимо передавать в виде пакета для преобразования; а значит ХSLT по сути в состоянии ее обрабатывать.
  • Последовательности. Одна из причин задержки с выходом ХSLT 2.0 в свет - ограничения по XPath. Оказалось, что законным образом создать внутреннюю функцию node-set() решительно невозможно. После основательных размышлений пришло-таки решение обеспечить поддержку общих последовательностей объектов - и ХML, и разрозненных данных других типов. Такое нововведение дало возможность более сложной группировки: (объединение, пересечение, различие) и свернутые списки, включая числовые повторения.
  • Числовые повторения (итерации). Теперь можно использовать выражения (1 to 10), которые будут возвращать увеличивающиеся повторяющиеся значения, а значит куда как меньше нужды в рекурсивных выражениях, что ведет к упрощению базы кода независимо от количества разнообразных операций.
  • Регулярные выражения. И ХSLT 2.0, и XPath 2.0 поддерживают данные выражения, а равно и строковые функции, позволяющих воспользоваться удобством регулярных выражений. Например, функция tokenize() может разбить строку на последовательность, основанную на регулярных выражениях (или сплошной текст), что значительно облегчает разбивку строк и полей в CSV файлах, извлечение данных из нестандартных форматов телефонных номеров, выполнение операций с парой слов в пределах данного набора письменных знаков того и другого, и тому подобное. В общем-то, так можно с помощью ХSLT сделать общую проверку по схеме, а также основательно способствовать генерации выходных данных в соответствии со Schematron.
  • result-document и выходные данные. Этот элемент позволяет отправить контент (необязательно только в ХML) в файл или веб-сервис независимо от механизма вывода, используемого в трансформации. Есть два ограничения для result-document: асинхронизированные события POST и возможность контроля лишь небольшого числа заголовков НТТР (в зависимости от реализации).
  • Контрольные ключевые слова. ХSLT 2.0 теперь поддерживает расширения XQuery (не все, но значительную часть) для итеративных вычислений с применением for петли или разнообразных операций на основе условных инструкций прямо в XPath, что может в немалой степени уменьшить размеры файлов и в целом облегчает чтение кода.
  • Таблицы кодов символов. В ХSLT 2.0 можно создавать такие таблицы, что позволяет располагать символы для форм вывода определенным образом. Таблицы кодов заменяют довольно громоздкую (и мало используемую) функцию disable-output-escaping , что обеспечивает верную постановку при выводе специфических знаков (подобных символу "меньше" "<" ). Это представляется очень полезным при создании промежуточных ХML структур, которые, тем не менее, обрабатываются посредством других ХSLT обращений, более того, также полезно для генерации файлов вывода, похожих на ХML, но не вполне им тождественных (таких как .jsp страницы, где могут встречаться строчные элементы типа <% %> ). Пример такой записи:
    <jsp:setProperty name="user" property="id" value="<%= "id" + idValue %>"></jsp:setProperty>
    Думаю, что это интересная функциональная возможность, открывающая ХSLT простор к применению в генерации логики обработки данных, что приложимо к большинству языков веб-серверов.
  • Сквозные параметры (Tunnel parameters). Параметризация никогда не вязалась с рекурсивной сущностью ХSLT, что нередко становится помехой разбиению на модули. В общем случае, если параметры расставлены по элементам, вызываемый шаблон должен их объявить, даже если задача состояла единственно в том, чтобы направить параметры в некий другой вызываемый шаблон по нисходящей последовательности. А вот в 2.0 запускается with-parameter обращение, содержащее сквозной атрибут со значением yes. Таким образом, параметр объявляется только тем шаблоном, в котором наличие значения параметра насущно необходимо, но никак ни одним из промежуточных шаблонов.
  • Типы данных. Для "упертых" ХSLT программистов это понятие вроде как "ни то, ни сё". Если вы определились, что конкретные переменные рассматриваются как принадлежащие к особому типу данных (при условии, что поддерживается весь набор простых типов XSD), результаты дальнейших операций с ними будут отнесены к тому же типу данных. Вдобавок, если ХSLT процессор читает схему, данные типы автоматически попадают в infoset, далее предполагается, что операнды принадлежат к уже распознанным типам.
  • Автономная обработка. Кроме того, возможен запуск ХSLT трансформации без дополнительного ХML файла для операций. Это, конечно, не столь серьезное преимущество, но в системах маршрутизации работает весьма эффективно.

XSLT 2.0 как маршрутизатор

ХML сообщение, полученное системой, предполагает определенную обработку. Одна из фундаментальных отличительных особенностей сетевых моделей программирования касается вопроса о том, где обрабатывается документ. Иными словами, что отвечает за указание на место постоянного размещения сообщения. В режиме REST местоположение задается исключительно URL: само по себе сообщение содержит связанные данные, но в нем нет релевантного местоположения. С другой стороны, в режиме RPC ответственность за обработку оформлена в виде пакета (обычно SOAP сообщение), где могут содержаться параметры, направленные на запуск метода на другом языке, вроде Java или C#.

Теперь, предположим, создано ХSLT 2.0 преобразование, связанное с парой неких других внешних объектов в соответствующем пространстве имен. Обычно невозможно запустить ХSLT преобразование, созданное другой трансформацией за один проход, все равно какой версии (этого и не должно происходить по соображениям безопасности). Тем не менее, определенно можно создать систему двойной передачи, где первый элемент строит из входящего сообщения одно или несколько преобразований, которые запускают соответствующие внешние методы класса в автономном режиме, которые в свою очередь передают результаты в выходной поток или генерируют вторичные потоки для передачи вновь созданного ХML документа в разные места.

Этот подход достаточно плодотворен. Во-первых, документы изначально принадлежащие к ХML-формату трансформируются как ХML. Так, в процессе преобразований можно провести тестирование того, насколько входящие данные не только корректно оформлены, но и бизнес-валидны, к тому же, это защита системы от потенциально опасных атак. Если Schematron тоже генерирует ХML, можно вернуть сообщения по тому же каналу (при наличии такого способа связи), в которых обрисовать в удобной для пользователя форме, где произошел сбой.

Во-вторых, так легче приостановить запуск потенциально высоко ресурсоемких операций на сервере, если в подобных вызовах превышен некоторый параметр (к примеру, количество автоматических запросов от определенного клиента). Поскольку информация обрабатывается в формате ХML, целостность системы не подвергается опасности несанкционированного ввода.

Первый процесс позволяет создавать пакеты из множества заданий: как только задание (командный запрос, например) или какая-либо дополнительная обработка выполнена, она удаляется из стека и ХSLT может перейти к обработке остальных заданий в стеке, на основе условного выражения, возникающего из предшествующей обработки заданий. Можно сказать, что ХSLT в такие моменты действует как язык управления заданиями, основанный как на входящих данных, так и на результатах их обработки.

Такие вызовы могут (а в общем-то и должны бы) быть асинхронизированными. Первый ХSLT-документ подвергает прежде обработанный ХML документ повторному асинхронизированному преобразованию с применением result-document, который затем извлекается в виде сообщения из ряда последовательных сообщений. В данном конкретном случае эффективная маршрутизация происходит только в рамках первого ХSLT документа, когда создавать многочисленные синхронизированные цепочки преобразований по большому счету излишне. Такая система применяет ХSLT как маршрутизатор сообщений, и то, что он может одновременно служить валидатором неслучайно. Одно из достоинств ХML - это возможность проверить правильность ХML-документа без создания экземпляра объекта.

XSLT 2.0, XQuery, и XForms

За многие годы я немало написал про XQuery. Должен признаться, он не произвел на меня особого впечатления, так как показался неким несуразным аналогом XSLT. Я подумывал о возможности использования XQuery для извлечения контента, который мог бы быть преобразован с помощью XSLT в подходящий формат. Пока мне не попалась на глаза база данных eXist, мне казалось, что эти процессы происходят по отдельности. Оказалось, что в eXist можно обращаться к расширениям transform:transform() для запуска преобразования над узлом ХML. После быстрой загрузки и некоторой настройки файлов конфигурации можно переключиться с преобразователя по умолчанию Xalan на Saxon 8.9, который поддерживает XSLT2, XPath2, и XQuery в одной и той же системе. Таким образом, XQuery можно напрямую превратить в веб-сервис.

Такое вот замечательное сочетание получается, что вы ни на минуту не выходите из ХML контекста. Не приходится тратить кучу времени на написание разных конфигураций для объектов преобразования, ресурсов XML Document, каналов связи, параметров, и т. п. В сущности, если рассматривать процесс в целом, работа с ХML по большому счету заканчивается. В сочетании с этим возможность оперировать разнообразными серверными объектами (запрос, ответ, сессия и пр.) дает полный контекст приложения в одной только программе XQuery.

Это становится особенно важно при работе с XForms. Выясняется, что чем далее, тем более непросто не работать с XForms, даже, признаться, с учетом сложностей, связанных с разными реализациями. С применением XForms можно выстроить модель данных ХML на стороне клиента, послать ее в XQuery, которая ее проверит и обработает, потом этот объект, в свою очередь, подвергается преобразованию для генерации еще одной копии XForms, XHTML отчета, какого-нибудь SVG графика. XSLT2 неплохо справляется с построением подобных шаблонов ввода и снова дает возможность тонкой настройки контроля условий и установки мощного интерфейса. Наверное, модель "Х" - XQuery + XSLT2 + XHTML + XForms - в будущем еще скажет свое веское слово. К ней уже присматриваются в разных отраслях, особенно в медицине, страховании, государственных и образовательных учреждениях.

Будущее XSLT

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

Итак, очевидно XSLT 2.0 в ближайшие пару лет будет все более востребован по мере появления новых разработок, особенно если иметь в виду, что разработки по XSLT 1.0 в настоящее время существуют почти для всех ныне используемых платформ, что делает ее в высшей степени успешным универсальным решением. Однако тем, кто бьется с малоуправляемыми рекурсивными стеками, с трудом вызываемыми шаблонами, кому разработки не приносят ничего, кроме головной боли, на скорое избавление рассчитывать не приходится.