Андрей Смирнов
Время чтения: ~24 мин.
Просмотров: 2

Практический xslt. использование в качестве шаблонизатора

Содержание:

  • HTML
    • Что такое HTML
    • <!DOCTYPE>
    • Мета теги в <head>
    • Тег <base>
    • Текст в html
    • HTML списки
    • Ссылки
    • Картинки на сайте
    • Таблицы
    • Фреймы
    • Формы
    • DHTML
    • Музыка
    • Видео
    • Карты изображений
    • SVG карты
    • Графика в HTML
    • SSI .shtml
    • Таблица цветов RGB
    • Правильноесочетание цветов
    • Таблица«безопасных»цветов
    • Таблица символов
    • Примеры HTML, CSS
  • CSS
    • Таблицы стилей CSS
    • Свод стилей
    • Псевдоклассы CSS
    • Псевдоэлементы CSS
    • CSS-градиент
    • Flexbox
    • Адаптивная верстка
    • @media screen
  • JavaScript
    • Описание языка
    • Методы и функции
    • Объекты
    • Строки
    • Формы
    • Фреймы и окна
    • Регулярныевыражения
    • Условнаякомпиляция
    • Примеры скриптов
    • Отладка
    • Оптимизация
    • Игры на JS
    • CSS из JS
  • PHP + MySQL
    • Введение в PHP
    • Основы языка
    • Использованиемассивов
    • $_server
    • Создание функций
    • Строки
    • Функции работысо строками
    • Объектноепрограммирование
    • Формы
    • Файлы
    • Загрузка файлов на сервер
    • MySQL
      • Дата, время MySQL
      • Вопросы по MySQL
    • Cookie
    • htaccess
    • Безопасность
    • Сессии
    • Отправка почты
    • Кэширование
    • Дата, время
    • Математическиефункции
    • Дополнительныевозможности
    • Регулярныевыражения
    • Библиотека Curl
    • IMAP, POP3, NNTP
    • Оптимизация
    • Примеры скриптов
  • XML + XSLT
  • AJAX
    • Знакомство с Ajax
    • ОбъектXMLHttpRequest
    • СозданиеAjax-приложения
    • Отправка формы
    • Области применения
    • Ajax примеры
    • АльтернативныеAjax-у методы
    • Ошибки Ajax
    • Навигация на AJAX
  • Графика CorelDRAW
    • Типы графики
    • Пакет CorelDRAW GS
    • Зимняя картинка
    • Осколок стекла
  • SEO
    • Анализ сайта
    • WEB продвижение(оптимизация)
    • Информацияо домене
    • Информация обIP-адресе
    • Ping поисковыхсистем
    • Robots.txt
    • meta Robots
    • Каталоги ипоисковики
    • Особенности SAPE
    • Page Rank
    • Сервис созданияссылок
    • О Контекстнойрекламе
  • Сервисы
  • Разное
    • Движки сайтов (CMS)
    • Хостинг
    • Настройка DNS
    • ADSL
    • RSS
    • ActiveX и HTML
    • Паролированиестраницы
    • HTTP коды
    • HTTP протокол
    • HTTP заголовки
    • Прячем ссылки
    • Черный списоксайтов
    • ☭ Заработокв интернете
    • Термины иопределения
    • Продажа доменов
    • НастройкиЯндекс-почты
    • Кнопки социалок
    • Настроки SIPв телефоне
    • Созданиепоискового плугина
    • Сервискоротких ссылок
    • Telegram: бот, ссылки.
    • Друзья
    • Статьи Liex
    • Задания к л/р
    • Примерызачетных задач
  • Статьи, обзоры
    • Шаблоны сайтов
    • Новости

Angular XSLT module

Из песочницы

Недавно мне попался маленький проект, где я предложил использование Angular и XSLT, на что я получил такой вопрос: «С чего бы использовать устаревшую технологию XSLT, ведь ее используют только с Java, да к тому же, только для Enterprise»?
Этот вопрос и явился причиной того, что я решил написать данную статью.
Итак, разрешите представить вашему вниманию «химеру» под названием Angular XSLT module. Ангулар разделяет business логику и view логику, но с модулем XSLT, view логику Angular можно вообще отдать XSLT.
Есть конечно пара подводных камней, это:
1) Результат не будет рендерится,
2) Angular команды не будут вызываться.
Но легким движением руки, эти проблемы решаются на раз-два!

Использование xslt-шаблонов в реальных проектах

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

1. Структура проекта

Обычно страница сайта состоит из нескольких общих блоков (меню, футер, …) и контентной части, которую для общности будем называть основным блоком. Все эти блоки размещаются внутри некоторого индексного шаблона, который знает в каком месте какой блок отобразить: меню должно быть вверху, основной блок в центре, а футер внизу.
Получаем следующую структуру

Контроллер главной страницы кабинета пользователя работает следующим образом:

  1. получает данные для основного блока, обрабатывает их с помощью /themes/cabinet/main.xsl и результат (готовый html) помещает в итоговый xml
  2. аналогично обрабатывает данные для других блоков (меню, футер) и результат помещает в xml
  3. итоговый xml, в котором находятся данные всех блоков, обрабатывает с помощью индексного шаблона /themes/index/main.xsl и результат отдаёт пользователю в виде html.

Обрабатываем и делим XML файл

Нам надо разделить статью на часть с текстом статьи и несколько частей которые буду содержать комментарии.

В браузере пользователя сразу будет отображена часть с текстом с статьи и по мерере загрузки частей комментариев будут появлятся и они.

Поскольку работать мы будем с XML файлом, то почему бы операции с ним не доверить также XSLT шаблонам.

Задаём межстраничные связи комментариев

Шаблону задаётся количество комментариев на один XML файл и он комментариям дописывает атрибут ‘страницы-ответов’, в котором перечисляются индексы XML файлов, в которых будут находится ответы на этот комментарий.

xslt\задать-страницы-ответов.xslt:

Определяем индекс последнего XML файла с комментариями

Шаблон просто делит количество комментариев всего на количество комментариев на страницу и выводит целое число меньшее или равное результату.

xslt\индекс-последней-страницы.xslt:

Делим комметарии на диапазоны

Шаблон выбирает из статьи комментарии для заданного индекса(‘страница’) XML файла.

xslt\выделить-диапазон.xslt:

Шаблон удаляет все комментарии, оставляя только текст статьи.

xslt\убрать-комментарии.xslt:

Собираем в браузере

Прогрессивная загрузка

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

прогрессивная-загрузка.xslt

Этот шаблон загружает основной текст статьи и подгружает комментарии из всех XML файлов.

сборка-статьи.xslt

Тестируем

Включаем в браузере ограничение скорости GPRS и запускаем загрузку страницы.

Загрузка текста статьи: 2,28с
Загрузка первых комментариев: 14,41с (только в FireFox)
Полная загрузка: 11,33 мин

Описание и примеры¶

Как можно заметить, элемент абсолютно идентичен элементу (отличаются только их имена). Практически настолько же похоже и их действие: элемент тоже связывает с именем параметра значение, и при выполнении шаблона это значение будет использоваться вместо значения параметра по умолчанию.

Таким образом, значение параметра, заданного в шаблоне, выбирается в соответствии со следующими положениями:

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

Элемент может использоваться только в качестве дочернего элемента и .

В качестве простого примера приведем шаблон, который выводит сокращение названия для недели по его номеру. Номер дня передается в шаблон параметром с именем .

Листинг 5.26. Вывод названия дня недели по номеру

Результатом вызова:

будет текстовый узел «». Рассмотрим теперь случай, когда параметра передано не было:

Шаблон выведет задумчивое , поскольку значение параметра будет по умолчанию нулем (атрибут имеет вид ) и в операторе выбора сработает условие .

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

Пример

Представим себе описание меню в следующем формате:

Для того чтобы при обработке особым образом выделять текущую страницу, определим в шаблоне параметр и будем выводить название страницы в элементе (от англ. bold — полужирный), если значение равно индексу данного пункта меню; если текущая страница и индекс пункта меню не совпадают, то выводиться будет ссылка.

Результатом выполнения шаблона

будет фрагмент меню вида

Попробуем теперь обработать элементы , не указывая значение параметра :

Результат будет получен в виде:

Этот фрагмент выходящего документа легко объяснить. Вследствие определения:

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

Мы упомянули, что значением параметра может быть дерево. Попробуем пояснить эту концепцию на примере генерации HTML-документа.

Итак, предположим, что мы генерируем выходящий документ следующим именованным шаблоном:

Параметр по умолчанию будет содержать дерево, состоящее из элемента и его дочернего элемента , который содержит текст «Title one». Результат выполнения вызова

мы можем видеть на следующем листинге:

Выделенный фрагмент относится к части дерева, которая была создана копированием значения параметра .

Попробуем теперь передать в качестве параметра дерево, сгенерированное следующим шаблоном:

Для того чтобы передать результат выполнения этого шаблона в виде значения параметра именованному шаблону , воспользуемся следующей конструкцией:

Выходящий документ будет получен в виде:

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

Атрибуты

К атрибутам можно обращаться также, как и к элементам. Надо только поставить
«@» перед именем атрибута.

Пример 15

Исходный XML

<?xml version="1.0" encoding="WINDOWS-1251" ?>
<?xml-stylesheet type="text/xsl" href="t15.xsl" ?>
<полка1>
<книга isbn="5-7890-0248X"> 
     <данные название="Web-технологии"
     автор="Колесников Д.Г."/> 
</книга> 
</полка1>

Атрибуты можно обрабатывать аналогично элементам.

Пример 16

Исходный XML

<?xml version="1.0" encoding="WINDOWS-1251" ?>
<?xml-stylesheet type="text/xsl" href="t16.xsl" ?>
<полка1>
<книга isbn="5-7890-0248X">"Web-технологии"
</книга> 
</полка1>

Преобразование XSLT ( файл t16.xsl )

<?xml version="1.0" encoding="WINDOWS-1251" ?>
<xsl:stylesheet version = "1.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="книга"> 
     <xsl:value-of select="."/> 
     <xsl:text> [</xsl:text> 
     <xsl:apply-templates select="@isbn"/> 
     <xsl:text>]</xsl:text> 
</xsl:template> 
<xsl:template match="@isbn"> 
     <b> 
         <xsl:value-of select="."/> 
     </b> 
</xsl:template>
</xsl:stylesheet> 

РЕЗУЛЬТАТ ПРИМЕРА 16:

«Web-технологии» [5-7890-0248X]

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

Пример 17

Исходный XML

<?xml version="1.0" encoding="WINDOWS-1251" ?>
<?xml-stylesheet type="text/xsl" href="t17.xsl" ?>
<source>
     <BBB id="b1" checked="yes"/> 
     <BBB id="b2" checked="yes"/> 
     <BBB id="b3"/> 
</source> 

Преобразование XSLT ( файл t17.xsl )

<?xml version="1.0" encoding="WINDOWS-1251" ?>
<xsl:stylesheet version = "1.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="BBB"> 
     <p>
          <xsl:text>BBB: </xsl:text> 
          <xsl:value-of select="@id"/> 
     </p> 
</xsl:template>
</xsl:stylesheet> 

РЕЗУЛЬТАТ ПРИМЕРА 17:

BBB: id=b1

BBB: id=b2

Преобразование из примера 18 исключает элементы, содержащие указанный атрибут.

Пример 18

Преобразование XSLT

<?xml version="1.0" encoding="WINDOWS-1251" ?>
<xsl:stylesheet version = "1.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="BBB"> 
     <p>
          <xsl:text>BBB: </xsl:text> 
          <xsl:value-of select="@id"/> 
     </p> 
</xsl:template>
</xsl:stylesheet> 

РЕЗУЛЬТАТ ПРИМЕРА 18:

BBB: id=b3

Пагинатор (постраничная навигация) на XSLT

Время от времени всплывает умирающая технология XSLT и задаёт непростые вопросы. Как, например, взять максимум от 2 чисел в выражении или как организовать цикл. Соединением многих таких вопросов служит пагинатор — вывод навигации по нескольким страницам и, по возможности, удобный. На Javascript есть много примеров простых и удобных пагинаторов. Но если страницы с сервера выдаются в XML, то возникает крамольная мысль: почему бы всё оформление страниц, включая пагинатор, не сделать на статике, в XSLT? Ничего, что в эту статику можно включить JS и сделать всё проще. Кошерный подход лёгких путей не ищет.

Описание и примеры¶

Синтаксис импорта преобразования практически полностью аналогичен включению: обязательный атрибут содержит URI внешнего модуля, который должен быть импортирован в текущее преобразование. Так же, как и в случае с , элемент логически заменяется содержимым внешнего модуля, и относительные идентификаторы ресурсов (URI), используемые во внешнем преобразовании, отсчитываются от его базового адреса. Преобразование не может прямо или косвенно импортировать само себя.

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

Порядок импорта

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

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

Эти правила могут быть проиллюстрированы следующими примерами.

Рассмотрим преобразование , которое импортирует преобразования и и включает преобразование .

Листинг 4.14. Фрагмент преобразования

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

  • bravo.xsl
  • charlie.xsl
  • alpha.xsl delta.xsl

Преобразование будет самым младшим, а преобразования и — самыми старшими.

Заметим, что импортируемые преобразования могут и сами импортировать другие модули. В этих случаях вычисление порядка импорта несколько усложняется.

Техническая рекомендация XSLT предлагает решать эту проблему построением логического дерева импорта.

Пример

Рассмотрим следующую схему включений и импорта (табл 4.1).

Таблица 4.1. Включение и импорт преобразований

Преобразование Импортирует Включает
alpha.xsl bravo.xsl charlie.xsl
bravo.xsl delta.xsl echo.xsl foxtrot.xsl
charlie.xsl golf.xsl hotel.xsl
hotel.xsl india.xsl

Этой схеме будет соответствовать логическое дерево импорта на рис. 4.1.

Рис. 4.1. Обход дерева импорта преобразований

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

Таким образом, порядок импорта преобразований от младших к старшим будет выглядеть следующим образом:

  • delta.xsl
  • echo.xsl
  • bravo.xsl foxtrot.xsl
  • golf.xsl
  • hotel.xsl india.xsl
  • charlie.xsl
  • alpha.xsl

Порядок, в котором импортируются модули, непосредственным образом влияет на различные аспекты преобразования. Эффект, который оказывает порядок импорта на те или иные элементы, будет подробно описан при их рассмотрении — сейчас же мы их просто коротко перечислим.

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

Преобразование даты в международный формат(UTC). Шаблон для версий XSLT от 1.0

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

  • Разбиение исходной даты в нашем формате на составляющие.
  • Определение смещения часового пояса относительно UTC учитывая переход на зимнее/летнее время, для москва летом смещение -4, зимой -3. Переход на летнее время происходит в два часа ночи последнего воскресенья марта, переход на зимнее время в три часа ночи последнего воскресенья октября.
  • Перевод всех частей даты в UTC время
  • Сбор даты в UTC формате.

Подзадачи:

  • Поиск дня недели, используется формула Зеллера
  • Поиск количества дней в месяце
  • Проверка года на високосность

Исходный шаблон даты:
DD.MM.YYYY hh:mm:ss
Подправить XSL под ваш формат можно без проблем, достаточно изменить последовательность разрезания и указать разделители.
Формат UTC даты:
YYYY-MM-DD hh:mm:ss
Подправляется еще проще, при сборе конечной строки.
Если требуется другие значения смещения часового пояса, достаточно исправить их в функции MoscowOffsetTime.
Использование шаблона:

XML-СУБД eXist

eXist-db — это система управления базами данных (СУБД) с открытым исходным кодом, построенная полностью на XML-технологиях (XML-СУБД). Она поддерживает, помимо других стандартов, XQuery, XPath и XSLT. СУБД eXist хранит данные согласно XML-модели данных и обладает высокой степенью совместимости со стандартом XQuery. Хранящиеся данные обрабатываются с помощью XQuery с использованием индекса. Кроме того, эта СУБД поддерживает полнотекстовый индекс на основе Apache Lucene.

XQuery-механизм, применяющийся в СУБД eXist, является расширяемым; соответственно в состав eXist входят различные модули расширения XQuery. Эти модули поддерживают следующие функции расширения XQuery.

  • Глобальный кэш пар «ключ-значение»
  • Разнообразные операции сжатия
  • Дополнительные операции с типами «дата/время»
  • Разнообразные операции с файлами и каталогами
  • HTTP-запросы (XPath-модуль)
  • Операции, применяемые к изображениям, хранящимся в базе данных (получение размеров изображения, создание миниатюр, изменение размеров изображения)
  • Применение интерфейса Java Naming and Directory Interface для доступа к таким каталогам, как LDAP, и для манипулирования этими каталогами
  • Отправка электронных писем в текстовом формате или в формате HTML
  • Календарное планирование выполнения заданий и управление существующими заданиями
  • Выполнение SQL-операций с реляционной СУБД
  • Выявление различий между XML-узлами
  • Представление XSL-FO
  • Функциональность XProc
  • Криптографические операции

И модуль eXist, и утилита написаны на языке Java. На момент написания данной статьи модуль eXist позволяет использовать в качестве XSL-FO-процессора процессор Apache Formatting Objects Processor (FOP) или процессор RenderHouse XEP. Посетите веб-сайт eXist для ознакомления с инструкциями по установке этой СУБД, которые помогут вам выполнить примеры из этой статьи.

eXist-модуль для цифровой публикации

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

Цель этого модуля состоит в том, чтобы служить единым источником для всех функций расширения XQuery, необходимых для цифровой публикации, в том числе для преобразования между следующими форматами: DocBook, Open XML, DOC, DOCX, .html, PDF, TXT, RTF, PPT, PPTX, CSV. Для установки этого модуля в среде eXist выполните следующие шаги:

  1. Загрузите eXist-модуль для цифровой публикации в формате JAR, а затем скопируйте его в каталог $EXIST_HOME/lib/extensions.
  2. Загрузите CSS-файл2xslfo1_6_2.jar, а затем скопируйте его в каталог $EXIST_HOME/lib/user.
  3. Добавьте в раздел встроенных модулей в файле $EXIST_HOME/conf.xml.

Генерация автоматических тестов: Excel, XML, XSLT, далее — везде

Из песочницы

Проблема

Есть определенная функциональная область приложения: некая экспертная система, анализирующая состояние данных, и выдающая результат — множество рекомендаций на базе набора правил. Компоненты системы покрыты определенным набором юнит-тестов, но основная «магия» заключается в выполнении правил. Набор правил определен заказчиком на стадии проекта, конфигурация выполнена.
Более того, поскольку после первоначальной приемки (это было долго и сложно — потому, что “вручную») в правила экспертной системы регулярно вносятся изменения по требованию заказчика. При этом, очевидно, неплохо — бы проводить регрессионное тестирование системы, чтобы убедиться, что остальные правила все еще работают корректно и никаких побочных эффектов последние изменения не внесли.
Основная сложность заключается даже не в подготовке сценариев — они есть, а в их выполнении. При выполнении сценариев “вручную», примерно 99% времени и усилий уходит на подготовку тестовых данных в приложении. Время исполнения правил экспертной системой и последующего анализа выдаваемого результата — незначительно по сравнению с подготовительной частью. Сложность выполнения тестов, как известно, серьезный негативный фактор, порождающий недоверие со стороны заказчика, и влияющий на развитие системы («Изменишь что-то, а потом тестировать еще прийдется… Ну его…»).
Очевидным техническим решением было бы превратить все сценарии в автоматизированные и запускать их регулярно в рамках тестирования релизов или по мере необходимости. Однако, будем ленивыми, и попробуем найти путь, при котором данные для тестовых сценариев готовятся достаточно просто (в идеале — заказчиком), а автоматические тесты — генерируются на их основе, тоже автоматически.
Под катом будет рассказано об одном подходе, реализующим данную идею — с использованием MS Excel, XML и XSLT преобразований.

Прогрессивная загрузка XML страниц

У нас есть очень большой XML. Это статья с очень большим количеством комментариев. На медленном и нестабильном мобильном интернете её загрузки можно и не дождаться. Во время загрузки случается обрыв связи и XML остаётся не догруженным. Казалось бы можно просто обновить страницу и браузер бы просто догрузил недостающую часть. Но нет. Браузер грузит страницу заново и снова это не удаётся и мы видим ошибку вместо страницы.

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

PHP-расширение dom_varimport: быстрое преобразования вложенных массивов в DOMDocument

Некоторые проекты используют XSLT в качестве основного «движка» шаблонов. Помимо известных недостатков XSLT (например, его многословности, относительной медлительности и т.д.) у него есть и преимущества: «стандартность» языка, его идеология отсутствия «побочных эффектов» и pattern matching, возможность при необходимости вызывать методы helper-классов из шаблонов (через exslt-расширение). Какое-то время назад я выкладывал библиотеку ShortXSLT, позволяющую вместо громоздких <xsl:value-of select=»/root/abc»/> и <xsl:choose>…</xsl:choose> писать просто {/root/abc} и {if…}…{elseif}…{/if} без потери производительности, так что проблема многословности отчасти решается.
Но сейчас речь не о преимуществах и недостатках XSLT (я уверен, и противники, и сторонники этой технологии найдутся в изобилии). Я бы хотел описать один прием, который удобно применять в существующих проектах с XSLT-шаблонами, и привести ссылку на библиотеку, реализующую данный прием с хорошей производительностью.

Передаем данные в XSLT, минуя генерацию текстового представления XML

Представьте, что у нас есть контроллер, генерирующий некоторый вложенный PHP-список объектов для отображения на странице. Он должен этот массив преобразовать в XML, который потом пойдет на вход XSLT-шаблону. Хорошо бы, чтобы данное преобразование из структур PHP в XML выполнялось не вручную в каждом контроллере, а был некоторый промежуточный слой абстракции, который умеет применять XSLT-шаблон прямо к PHP-данным, минуя текстовое XML-представление. Так мы уменьшим вероятность ошибок, да и письмо сократится. Мы сможем работать с XSLT-шаблонами напрямую, минуя XML-представление данных.
Некоторое время назад я написал на Си PHP-расширение dom_varimport (также выложено на GitHub). Оно содержит одноименную функцию, на вход которой подается объект DOMDocument и PHP-массив любой вложенности. Функция заполняет переданный ей DOMDocument XML-представлением входного массива, и делает она это очень быстро — примерно в 20 раз быстрее, чем делал бы код, написанный на чистом PHP. Большой документ размером около 1 МБ с тысячами вложенных свойств и объектов формируется примерно за 1-2 миллисекунды.
Например, вызов:

Примеры

В этом разделе анализируется использование утилиты
реализованной в eXist-модуле расширения XQuery для цифровой публикации. При решении этой задачи используйте XML-данные, представленные в , а также таблицу стилей XSLT (xml-to-html.xsl), включенную в пример кода (см. раздел .

Примечание:
Чтобы упростить восприятие этой статьи, я не привожу в ней все содержимое используемой таблицы стилей XSLT. Вместо этого я показываю лишь те элементы, которые делают эту таблицу стилей пригодной для преобразования XML в HTML и в PDF.

Примеры будут загружены в XML-СУБД eXist в виде коллекции с именем html-and-pdf-single-stylesheet расположенной в корневой коллекции eXist — это позволит вам просмотреть каждый пример в своем браузере. Например, чтобы просмотреть пример 1, введите в адресной строке своего браузера следующий URL-адрес (предполагается, что СУБД eXist установлена на локальной машине).

http://127.0.0.1:8080/rest/db/html-and-pdf-single-stylesheet/example%201/example1.xql

Чтобы значительно полнее использовать функциональные возможности инструмента
вам не потребуется никакой другой XQuery-код, кроме кода, показанного в
и
. Этот код представляет XML-данные в формате HTML и в формате PDF соответственно. Для дальнейшего совершенствования PDF-документов необходимо добавить CSS-инструкции в CSS-раздел таблицы стилей XSLT.

<invoices-summary> 
  <invoice id=""> 
    <issue-date>2011-10-17</issue-date> 
    <amount>108</amount> 
    <vat>19.47</vat> 
    <vat-base>22</vat-base> 
    <currency>EURO</currency> 
    <customer-id>0001008</customer-id>
   </invoice> 
  <invoice id=""> 
    <issue-date>2011-10-17</issue-date> 
     <amount>40</amount> 
    <vat>7.21</vat> 
     <vat-base>22</vat-base> 
     <currency>EURO</currency> 
    <customer-id>0000017</customer-id> 
  </invoice> 
  <invoice id=""> 
    <issue-date>2011-10-17</issue-date> 
    <amount>1700</amount> 
    <vat>306.56</vat> 
    <vat-base>22</vat-base> 
    <currency>EURO</currency> 
     <customer-id>0000040</customer-id> 
  </invoice> 
</invoices-summary>

Первый пример (см. ), представляет собой XQuery-скрипт, который преобразует XML-данные, представленные в в формат HTML. Этот скрипт использует eXist-функцию , которая, в свою очередь, преобразует XML-данные с помощью таблицы стилей XSLT и (при желании) параметров для преобразования. Вы можете написать таблицу стилей XSLT в соответствии со спецификацией XSLT 1.0 (средствами Apache Xalan) или в соответствии со спецификацией XSLT 2.0 (например, средствами Saxon).

Рисунок 1. Результат преобразования в формат HTML

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

Для простого сценария применения который описывается этой статье, такие инструкции расширения нам не нужны. Утилита преобразует HTML-документ в XSL-FO-документ, который, в свою очередь, генерирует PDF-документ, весьма похожий на HTML-документ.

После этого мы преобразуем результирующий HTML-документ в XSL-FO-документ с помощью функции , а затем генерируем PDF-документ (см. ). Для создания PDF-документа используется функция

eXist-модуля .

Рисунок 2. Результат преобразования в формат PDF

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

Java XML API: выбираем правильно

  • JAXP (Java API for XML Processing) это набор API (SAX + DOM + валидация DTD + XSLT). Xerces и Xalan — стандартные реализации этих API. Кроме XSLT все API устарели: на смену SAX пришел StAX, DOM сменил JAXB, DTD заменил XSD.
  • DOM и JAXB — API для полного зачитывания XML и получения в приложении его готового представления в объектах Java. Для DOM это коллекции реализаций интерфейса org.w3c.dom.Node (атрибуты, элементы, текст, ..). Для JAXB задается мапинг, наподобие тому, как в ORM задаются отображения таблиц базы данных в объекты Java. Т.е. из XML получаются готовые и удобные в использовании Java бины. JAXB — наиболее удобный и часто используемый API для работы с XML, когда требуется почитать весь XML (он должен поместиться в память JVM) и выполнить с ним требуемые действия.
  • DTD (устаревший) и XSD — схемы, задающие проверку структуры XML (порядок следования элементов, обязательность или опциональность элемента, наличие атрибутов у элемента). К XML можно привязать схему проверки структуры, и тогда инструменты, работающие с XML (например IntelliJ IDEA) могут делать автодополнение и показывать ошибки схемы. Также можно провалидировать XML документ из приложения. Формат XSD более современный и сам является XML документом.
  • XPath язык запросов к XML. Грубо можно сравнить с запросом SQL к базе данных, кода нам нужно достать из XML какой-то определенный элемент (или элементы) или подсчитать их количество. Я видел их применение, например, в ESB: данные между системами передаются в XML формате и в конфигурации каждая система через XPath «выкусывает» из XML нужные ей данные. Чаще всего XPath используется при трансформации XML.
  • XSL, XSLT — преобразования XML в любой другой формат. Одно из применений, например, отдать с сервера в браузер ответ в виде XML и задать его XSL-преобразование в HTML. Все современные браузеры поддерживают XSLT преобразования, т.е. на стороне клиента самостоятельно трансформируют XML по заданной XSL к требуемому виду.
  • SAX и StAX — последовательное чтение из источника XML.Документ читается последовательно по кусочкам (событиям). API между собой отличаются тем, что SAX основан на модели push, а Stax на модели pull. Если вы когда-то делали на javascript несколько последовательных AJAX запросов, то сталкивались с callback hell. Выполнение кода делается асинхронно и код пишется не последовательно, а ступеньками в функциях возврата. При использовании SAX происходит нечто подобное: нужно задавать функции для обработки определенных событий в XML (начало тэга, конец тэга, текст внутри тэга, комментарий) и внутри этих обработчиков задавать новые обработчики. Работать со StAX гораздо удобнее. Мы последовательно читаем из документа события, анализируем их и обрабатываем подходящие. Эти API используются при очень больших документах, из которых зачитываются списки объектов по одному по мере их появления в документе, либо когда нам интересен не весь документ, а его определенная часть и модель всего документа не нужна.

Timestamp из даты-времени с помощью XSLT

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

  1. Дата и время разделялись пробелом, а не буквой ;
  2. Число цифр, обозначающих миллисекунды могло варьироваться от «ниодной» до «много-много»;
  3. Часовой пояс не указывался вообще.

Сначала я хотел воспользоваться готовым решением с exslt.org – , но от него пришлось отказаться. Дело в том, что разницу требовалось получать с точностью до миллисекунд, а этот алгоритм возвращал валидный (ISO 8601), который миллисекунд не содержит. К тому же парсить чужой output, хоть и формализованный – дело не очень благодарное. Таким образом, покопавшись немного в exslt, я решил написать парсер сам, в надежде, что смогу сделать это быстро…

Заключение

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

Похожие темы

  • Веб-разработка на основе XRX: Ознакомьтесь с дополнительной информацией о среде XRX.
  • Руководство пользователя утилиты CSSToXSLFO: ознакомьтесь с новыми идеями по таблицам стилей и форматированию.
  • Веб-сайт СУБД eXist с нативной поддержкой XML: загрузите СУБД eXist и получите инструкции по ее установке.
  • The : загрузка с ресурса Google Code.
  • The utility: загрузка с ресурса SourceForge.
Рейтинг автора
5
Материал подготовил
Максим Иванов
Наш эксперт
Написано статей
129
Ссылка на основную публикацию
Похожие публикации