Об XSLT шаблонизаторе


Об XSLT шаблонизаторе

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

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

Начнем с азов.

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

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

Если мы используем второй способ (вывод в браузер), то, чтобы эти данные опознал браузер как XML поток и представил в удобопонимаемом виде, необходимо выдать заголовок Content-type: text/xml:

Необходимо отметить, что когда пишется XSL-шаблон, то это уже не HTML, а XML, и надо руководствоваться правилами валидности XML:

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

    .
  • Если тег представлен без пары (одинарный), то он должен иметь закрывающий слэш. Это в основном касается таких одинарных тегов, как
    и .
  • Практически это означает, что нельзя перемешивать теги, должна быть четкая иерархия вложенности. Например, такие конструкции как: bla-bla-bla bla-bla-bla bla-bla-bla валидны в HTML, но недопустимы в XML.

    Использование включений

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

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

    В XSLT-преобразованиях есть аналогичный механизм >xsl:include / .

    Имеется файл main.xsl, который содержит «генеральный» шаблон, единый для всех страниц:

    В данном шаблоне есть правило , которое применяется ко всем элементам xml-документа. Данная инструкция, может быть заменена на .

    В нашем преобразовании должна быть инструкция и, соответственно, шаблонное правило, определенное в «генеральном» шаблоне:

    Если мы используем в «генеральном» шаблоне инструкцию то вместо используем именной шаблон: . В этом случае и технология разработки шаблонов – иная.

    В любом случае при использовании «генеральных» шаблонов надо придерживаться строго определенного формата выходных xml-данных.

    Например, у меня следующая структура:

    Под > понимается имя тега, соответствующему экшену в модуле, например, для экшена edit буде тег . Но разработка структуры — дело сугубо индивидуальное.

    В заключение хотелось бы заметить, что при использовании XSLT-процессора sablotron (версия php 4) необходимо определить базовую директорию, где лежат файлы включений, функцией xslt_set_base($xh, $filebase) , где переменная $filebase должна содержать полный путь к директории.

    Если что-то не получается.

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

    Как правило, разработка шаблонов соответствует порядку разбора шаблонов, т.е. начинается с корневого элемента xml-данных. Может само обрамление дизайна – это уже дело рук самого дизайнера, но заготовку в виде пустого шаблона надо предусмотреть. И пошли так далее, углубляясь по ходу обработки структуры xml- данных.

    Если шаблон ничего не выводит, то надо проверить:

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


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

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

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

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

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

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

    Результатом применения будет текст, содержащий имя текущего узла, обрамленного тегами .

    Иногда полезно знать положение узла в контексте, тогда применим функцию position() к текущему узлу. Использование этой функции позволяет нам увидеть динамику прохода, т.е. применение шаблонных правил к текущей ветке xml-документа. Как правило, функцию position() применяют в циклах , но иногда применяют и к вызовам шаблонных правил.

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

    Ближе к практике. Сортировка.

    Одна из часто применяемых практических задач – это вывод отсортированной таблицы, причем критерий сортировки определен данными, т.е. при разработке шаблона мы заранее знаем только перечень критериев, по которым будет производиться сортировка. Для примера возьмем прайс-лист, который можно отсортировать по:

    • цене
    • наименованию товара
    • наименованию группы товаров

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

    Значение атрибута sort корневого элемента root определяет, какой тип сортировки использовать. В данном примере используется сортировка по категориям товаров (type).

    Шаблон, обрабатывающий тег

    ,

    и «строящий» таблицу, будет выглядеть следующим образом:

    Для реализации данного шаблона использован XSLT-элемент , который определяет XSLT переменную $sort . Данная переменная содержит значение атрибута sort корневого элемента root .

    Для определения критерия сортировки использовались предикаты выборки. При вычислении предиката его результат приводится к булевому типу. Синтаксически предикат заключен в квадратные скобки, т.е. конструкция типа показывает, что сортировка будет осуществляться для всех узлов по ключу, соответствующему атрибуту @type , при условии, что значение переменной $sort будет равно стоковому выражению «type». Соответственно, по каждому критерию, по которому будет осуществлена сортировка, необходима своя команда .

    Заключение

    Конечно, количество всяких методов и приемов при разработке XSLT шаблонов множество и «нельзя объять необъятное». В настоящее время даже появились разные стили написания шаблонов. Я попытался охватить лишь первые этапы «Путешествия в страну Шаблонизации».

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

    Уже после написания данной статьи автор узнал о существовании инструментария XSLT-разработчика, включающее средства XSLT-отладки. Это такие программные продукты, как: xselerate, Stylus Studio, Altova XML StyleVision. Данные программные продукты являются платными.

    Автор будет благодарен за любую критику данного материала, а также будет рад услышать ваши пожелания и узнать, с какими же вы сталкивались трудностями при разработке XSLT–шаблонов. Все замечания будут учтены при подготовке следующей статьи из цикла: «Шаблонизация на XSLT».

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

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

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



    Получаем следующую структуру

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

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

    Индексный шаблон /themes/index/main.xsl может выглядет следующим образом:

    2. Именованные шаблоны

    Мы можем использовать этот шаблон как для отображения текущего пользователя

    так и для отображения списка пользователей

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

    3. Импорт шаблонов


    4. Ни строчки php-кода в представлении

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

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

    И даже больше, xslt позволяет вызвать эту функцию прямо из шаблона

    Но это не только противоречит заголовку раздела, но и является неким атавизмом. Лучше избегать вызовов php-функций внутри xslt-шаблонов.
    Что же делать? Есть 2 выхода:

    1. пусть контролер вызывает str_plural_form и отдаёт нужные данные
    2. сделать именованный шаблон-функцию, которую мы поместим в /themes/inc/functions.xsl

    Вызов функции будет выглядеть так

    5. Справочники

    Можно решить задачу влоб. При получении каждого из списков делать LEFT JOIN users и получать необходимые данные для вывода информации о пользователе. Но есть и отрицательные моменты такого решения. Первое — возможная избыточность данных (пользователи из списков могут повторяться), второе — дополнительная нагрузка на sql-сервер.

    Другой вариант решения задачи. Получить все списки. Затем из этих списков получить набор user_id. И по этому набору сделать один запрос к таблице users. Результат сложить в xml по известному адресу, например /ref_users.
    В итоге у нас должен получиться xml-документ с узлами posts, active_users, online_users, ref_users.

    Для вывода информации о пользователе сделаем такой именованный шаблон
    и сохраним его в /themes/models/user.xsl. Это шаблон для вывода пользователя по его id.

    Вывести список постов с информацией о пользователе можно так

    Заключение

    Ссылки по теме

    Популярные статьи
    Информационная безопасность Microsoft Офисное ПО Антивирусное ПО и защита от спама Eset Software


    Бестселлеры
    Курсы обучения «Atlassian JIRA — система управления проектами и задачами на предприятии»
    Microsoft Office 365 для Дома 32-bit/x64. 5 ПК/Mac + 5 Планшетов + 5 Телефонов. Подписка на 1 год. Электронный ключ
    Microsoft Windows 10 Профессиональная 32-bit/64-bit. Все языки. Электронный ключ
    Microsoft Office для Дома и Учебы 2020. Все языки. Электронный ключ
    Курс «Oracle. Программирование на SQL и PL/SQL»
    Курс «Основы TOGAF® 9»
    Microsoft Windows Professional 10 Sngl OLP 1 License No Level Legalization GetGenuine wCOA (FQC-09481)
    Microsoft Office 365 Персональный 32-bit/x64. 1 ПК/MAC + 1 Планшет + 1 Телефон. Все языки. Подписка на 1 год. Электронный ключ
    Windows Server 2020 Standard
    Курс «Нотация BPMN 2.0. Ее использование для моделирования бизнес-процессов и их регламентации»
    Антивирус ESET NOD32 Antivirus Business Edition
    Corel CorelDRAW Home & Student Suite X8

    О нас
    Интернет-магазин ITShop.ru предлагает широкий спектр услуг информационных технологий и ПО.

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

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


    Шаблонизатор на XML+XSLT

    Valentin

    Новичок

    Шаблонизатор на XML+XSLT

    Вопрос по реализации.

    Допустим, нужно реализовать простейший аналог html-шаблонизатора на xml-xslt.

    Я это себе представляю таким образом:
    имеется суппер-шаблон на xslt

    . // тут должны подключаться другие xslt-блоки

    Допустим, путь к этому шаблону хранится в переменной $index_template;

    В этот шаблон необходимо подключать другие xslt-блоки, типа, header footer menu news gb и т.д. Пути к этим шаблонам храняться в $blocks_templates

    А путь к этим xslt

    Данные XML динамически хранятся в объектах DOMDocument.

    Реально ли организовать буффер вывода, где все шаблоны-блоки (news.xslt, gb.xslt, menu.xslt, header.xslt, footer.xslt) $blocks_templates подключает суппер-шаблон (index.xslt) $index_template.

    Есть ли подобная реализация. Если есть, готов выслушать ваше мнение и пожелания

    Какой шаблонизатор использовать. PHP, XSLT

    Автор: beowulf13th · 23 Апр 2012

    Как бы не говнились программисты 1С:Битрикс, как бы не писали ужасные статьи, что XSLT — это сложно, страшно, тормознуто и вообще ужас какой-то, XSLT имеет право на существование, во всяком случае Я так считаю. И у меня на это несколько причин.

    1. Абстрагирование от логики. Достаточно просто описать XML, который мы будем выдавать, чтобы правильно написать XSL-файл. Главное не вносить в XSL какую-то логику. Единственное, что Я позволяю выбирать в XSL стилях — это какой класс будет у элемента, если @a = 1. Ну что-то в таком духе.

    2. Более понятное и наглядное представление. Кому как, а мне XSL шаблон нравится гораздо больше, чем мешанина из HTML и PHP, которая возникает при использовании PHP-шаблонизаторов или ещё хуже, при выводе HTML прямо из логики.

    3. Скорость работы. Я проверил на простых примерах, что работает быстрее. Скачать примеры PHP и XSLT можно внизу страницы.

    Результат этих тестов такой:

    Проверка времени выполнения прямого вывода из PHP за 1000 операций.
    Прямой вывод работал: 0.0025558471679688
    Проверка времени выполения с использованием подключаемого файла.
    Вывод через файл отработал работал: 0.13970184326172
    Вывод с использованием XSLT.
    Вывод с использованием XSLT работал: 0.025261878967285

    Прямой вывод как обычно побеждает. Но у него огромный недостаток — код становится нечитабельным. И попытки что-то изменить могут привести к неожиданным результатам.

    На втором месте — XSLT. Он в 10 раз медленнее прямого вывода, но в 5,5 раз быстрее вывода с использованием подключения файла шаблона в цикле. В принципе, есть вариант, когда мы выносим цикл в подключаемый, но это сводится к выводу из PHP. Поэтому Я 1000 раз подключаю файл шаблона. 🙂 И кстати, в примере с XSLT учитывается время создания XML, тогда как с PHP мы уже сразу выводим. Если будет готовая XML — время ещё уменьшится.

    И подключение файла шаблона оказывается на третьем месте.

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

    Элемент xsl:template


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

    Элемент

    Для создания шаблонов преобразования используется элемент .

    При этом атрибут match используется для ассоциации шаблона с XML элементом. Также, атрибут match может использоваться, чтобы определить шаблон для всего XML документа целиком. Значение атрибута match это выражение XPath (например, match=»/» определяет весь документ).

    Пример

    Объяснение

    Так как таблица стилей XSL это XML документ, он всегда должен начинаться с XML декларации: .

    Следующий элемент, , определяет, что данный документ это таблица стилей XSLT (с атрибутами номера версии и пространства имен XSLT).

    Элемент определяет шаблон. Атрибут match=»/» ассоциирует шаблон с корневым элементом исходного XML документа.

    Содержимое элемента определяет некий HTML код, который записывается в выходной документ.

    Последние две строки определяют конец шаблона и конец таблицы стилей.

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

    XSLT-шаблонизатор для PHP

    Привіт! Мене звати Артем, я — PHP-програміст. У цій статті розглянемо основи XSLT і приклади його використання як шаблонизатора для веб-сайтів, які створено мовою PHP.

    Зазвичай, коли створюють сайти з PHP, для динамічного формування HTML-сторінок виведення використовують один з багатьох Smarty-подібних шаблонизаторів. На моє глибоке переконання, XSLT у цій ролі дуже недооцінили, і я спробую виправити цю прикру помилку.

    Коли я лише починав вивчати PHP, шаблонизатори не використовували взагалі, а виведення даних з PHP у HTML було заведено здійснювати безпосередньо. Згодом з’явився та швидко набув популярності шаблонизатор Smarty, тож створювати представлення згідно з архітектурним шаблоном MVC стало набагато простіше й цікавіше. Але коли я випадково, читаючи все поспіль у посібнику про PHP, познайомився з XSL-трансформацією, то зрозумів, що підсів на неї й це надовго.

    Зізнаюся відверто, що не відразу зрозумів цю технологію, а тим паче оцінив її переваги. Насамперед мене спантеличувала парадигма програмування, яка істотно відрізняється від звичної для PHP об’єктно-орієнтованої, або навіть процедурної. До того ж мова Extensible Stylesheet складніша, як порівняти з тим же Smarty. І це не дивно, адже XSLT — цілком незалежна самодостатня мова, розроблена W3C як міжнародний стандарт для перетворення структур даних. Але згодом, коли мій мозок звик до нової парадигми, я зрозумів, що мої перестороги були марними.

    Документ у форматі XML за допомогою шаблонів XSL можна змінити на з іншою структурою або на HTML-сторінку, Plain Text чи навіть PDF. Але саме зараз нас цікавить на виході лише HTML. І для цього нам навіть спочатку не знадобиться PHP: більшість сучасних веб-оглядачів уміє здійснювати XSL-перетворення самостійно. Налаштуймо для цих потреб локальний тестовий веб-сайт (наприклад, цей) і створімо в ньому кілька файлів.

    Шаблони

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

    XSL-файл складається зі щонайменше одного або кількох шаблонів template . У них за допомогою простих інструкцій у вигляді XSLT-елементів, створюють нову структуру даних на основі вхідних даних. Або, інакше кажучи, шаблон XSLT описує, які дані з вхідного й у якому місці виводити (у цьому разі — поміж HTML), і як саме.

    Шаблони XSLT, так само як і функції в програмуванні, мають два призначення: основне й додаткове. Основне — це уникнення дублювання коду шляхом його повторного використання. А додаткове — поділ великих шматків коду на менші, зручніші для сприйняття.

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

    Шаблони в XSLT викликаються двома різними способами та мають різні підходи до області видимості вхідних даних XML у самому шаблоні. Я називаю їх, за аналогією з умовним переходом в програмуванні, шаблонами з умовним або безумовним викликом.

    Шаблон з умовним викликом застосовують за допомогою елемента apply-templates з атрибутом select , у якому вказано умову виклику шаблона. Виклик зактивізується лише тоді, коли хоч якась частина вхідного документа відповідає умові виклику. Цей тип шаблонів, по-моєму, є родзинкою XSLT і робить його таким, яким він є. Він за своєю природою реалізує принцип обробки потокових даних, а саме тут — ще й ієрархічної структури.

    Особливо зауважте, що звернення до вхідних даних XML у шаблоні, який викликали в такий спосіб, здійснюється відносно того елемента, який зазначено останнім в умові виклику шаблона. У першому прикладі звертання в самому шаблоні до даних здійснюватиметься відносно елемента country . У решті чотирьох випадків — відносно елемента city .

    Якщо ви хочете отримати дані з елементів чи атрибутів, які містяться за межами кореневого елемента цього шаблона, то до них можна звернутися або за допомогою абсолютного шляху (наприклад: /document/country/@title ), або за допомогою відносного (наприклад: ../@title ).

    Шаблон з безумовним викликом викликають за допомогою інструкції call-template і, на противагу попередньому, абсолютно без жодних умов. Як наслідок, в інструкції й у шаблоні, який вона викликає, указують власну назву шаблона — name , а не умову його застосування.


    За своєю суттю він — аналог виклику функції в програмуванні, за винятком підходу до області видимості даних. У разі виклику шаблона за допомогою цього способу доступ до вхідних даних відбувається так само, як і в місці виклику шаблона. Тобто цей метод виклику під час виконання ніби вставляє весь код із шаблона в те місце, де його викликають, замість інструкції виклику.

    Для того щоб краще зрозуміти шаблони, методи їхнього виклику й інші пов’язані із цим речі, пропоную створити невеликий практичний приклад. Створімо спочатку простенький templates.xml лише з кількома елементами.

    Хоча виклик шаблонів у різних режимах і використовують на практиці дуже рідко, але це дає можливість запускати два різних шаблони для однієї умови. Передавання параметрів у шаблон використовують частіше й, на відміну від режиму, можуть застосовувати для обох способів виклику шаблона.

    А тепер найцікавіше — процес трансформації. Запускаємо створений нами за адресою і насолоджуємося нашою першою HTML-сторінкою, згенерованою за допомогою XSL-перетворення з боку клієнта за допомогою веб-оглядача.

    Приклад роботи шаблонів в XSLT

    Якщо подивитися на початковий код сторінки, то побачимо там не HTML-теги, як ми звикли, а дані XML. І це правильно, тому що саму HTML-сторінку створює веб-оглядач, а для нього — це першоджерело.

    Для того щоб усе-таки побачити HTML-код новоствореної сторінки, потрібно скористатися внутрішніми інструментами розроблення, які надає веб-оглядач (наприклад Chrome DevTools). Якщо ви зробили все правильно, то код вашої сторінки матиме приблизно такий вигляд:

    Решта інструкцій

    Для демонстрації решти поширених XSLT-інструкцій я підготував новий приклад, який, на відміну від попередніх штучних, хоча б віддалено нагадує шаблон з реального проєкту.

    Але спочатку для демонстрації можливостей шаблона потрібно створити файл index.xml з певними структурою й даними.

    Стандарт XML, як і решта поширених форматів даних (CSV, YAML, JSON), настільки простий, що я не витрачатиму час на його опис. Лише в таблиці нижче наведу кілька прикладів найпоширеніших способів здійснення навігації в ієрархічній структурі за допомогою мови запитів XPath, яку, до речі, теж створили в W3C. Якщо вам цих прикладів буде замало, завжди можна підглянути в розділі «Синтаксис XPath».

    /root Пряме звернення до кореневого елемента root
    /root/@title Пряме звернення до атрибута title кореневого елемента root
    /root/menu Звернення до дочірніх елементів menu батьківського кореневого елементу root
    /root/menu/* Звернення до нащадків батьківського елемента menu кореневого елемента root
    menu/*/@title Відносне звернення до атрибутів title нащадків батьківського menu
    menu/item[1]/@section Відносне звернення до атрибута section першого дочірнього елемента item батьківського елемента menu

    А тепер створимо файл шаблона index.xsl , у якому з метою ознайомлення використаємо найпоширеніші XSL-інструкції.

    PHP + XML + XSLT = HTML

    Якщо у вас все вийшло й ви побачили HTML-файл, гадаю, ви неодмінно спробували перевірити роботу меню. Але під час переходів по його пунктах на сторінці нічого не відбувається, бо XSLT відповідає тільки за виведення інформації. А якщо ви хочете її змінювати залежно від дій користувача, потрібно створити хоча б якийсь примітивний контролер.

    PHP має дуже багато різних інструментів для роботи з XML, і найпростіший з них — це SimpleXML . За його допомогою можна працювати з надзвичайно просто, як з масивом чи об’єктом. Він може створювати новий чи відкривати наявний XML на основі рядка, уносити в нього зміни й зберігати його у файл чи конвертувати в рядок для виведення.

    Ось невеличкий приклад того, як просто з ним працювати:

    Спочатку за допомогою ми створили об’єкт SimpleXMLElement і встановили значення атрибута time в кореневому елементі. Потім за допомогою методів addChild та addAttribute додали елементи й атрибути в потрібному нам місці ієрархічної структури документа. І, нарешті, за допомогою методу asXML здійснили конвертацію об’єкта SimpleXMLElement у рядок та вивели його на перегляд.

    Тут все настільки просто, що я навіть не знаю, що ще можна додати. Зрідка трапляється, коли обмеженого функціонала SimpleXMLElement бракує. Тоді по допомогу треба звертатися до надзвичайно просунутого й, відповідно, набагато складнішого розширення DOM (Document Object Model) . Також варто звернути увагу на те, що для роботи з XML треба під’єднати в PHP розширення php_xml .

    Нарешті, як приклад я створив маленький скрипт на PHP, який надасть сторінці динаміки.

    А зараз, виконавши скрипт, отримаємо модифікований при переході пунктами меню якого зміст сторінки відповідно змінюватиметься.

    Приклад роботи XSLT разом з PHP

    Виконувати перетворення XSLT з боку клієнта для розробника дуже зручно: це частково зменшує навантаження на сервер. А для веб-оглядача клієнта ця трансформація не надто обтяжлива й відбувається абсолютно непомітно. Але водночас цей спосіб має один типовий недолік: невідомо, як саме різні веб-оглядачі здійснюватимуть це перетворення.

    Хоча XSLT — це єдиний, добре описаний і відкритий стандарт, але, як це часто трапляється, кожен тлумачить його на власний розсуд. До речі, так само, як і HTML та багато інших відкритих стандартів. Якщо поширені веб-оглядачі більш-менш добре впораються із цим завданням, то як відбуватиметься цей процес у менш поширених веб-оглядачах, передбачити неможливо. І якщо ви не маєте бажання ризикувати, то доведеться виконати це перетворення на стороні сервера за допомогою, наприклад, того ж PHP.

    Здійснити XSLT-перетворення PHP ми зможемо за допомогою об’єкта XSLTProcessor , який приймає XML як об’єкт DOMDocument . Тому перед XSLT-перетворенням треба здійснити конвертацію із SimpleXML у DOMDocument ( SimpleXML -> DOMDocument -> XSLTProcessor ). Як наслідок, доведеться замінити два останні рядки в нашому останньому прикладі на такий код:

    Сам процес трансформації має дещо заплутаний вигляд, але його достатньо раз прописати в кінці скриптів, і ви до нього не повертатиметеся. А для роботи з XML треба використовувати суперпростий SimpleXMLElement .

    До речі, робота з XSLT у середовищі PHP реалізується засобами скомпільованої системної бібліотеки libxslt . А це, зокрема, дуже позитивно позначається на швидкодії, як порівняти з іншими шаблонизаторами, які здійснюють таке перетворення за допомогою власних скриптів мовою PHP.


    У цій статті я намагався якомога більше спростити опис і приклади, щоб знизити поріг входження в цю дивовижну технологію. Маю надію, що мені це вдалося та згодом кількість адептів XSLT поступово, але невпинно збільшуватиметься. Так само, як і кількість сайтів, генерацію HTML-сторінок у яких зреалізували за допомогою цієї мови.

    XSL: шаблоны (xsl:template)

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

    Процесс xslt-преобразования выглядит следующим образом: XSLT-процессор анализирует исходный XML-документ, последовательно перебирая каждый его элемент. При этом для каждого элемента процессор пытается найти подходящий шаблон (template) в XSL-файле путем сопоставлении исходного элемента и содержащегося в шаблоне образца (pattern). Если подходящий шаблон не найден, используется шаблон по умолчанию и процессор переходит к следующему элементу в исходном XML-документе. Если подходящий шаблон (template) найден процессор выполняет содержащиеся в шаблоне инструкции (Template Rules – правила шаблона), на основании чего строится конечное дерево. При этом текущим узлом для шаблона будет являться обрабатываемый узел XML-документа. В шаблоне могут содержаться правила (инструкции), выбирающие новый текущий узел.

    Синтаксис:

    Атрибуты:

    • match – обязательный атрибут, задает образец (pattern), который определяет узлы исходного дерева, к которым данный шаблон должен быть применен. Образец записывается на языке XPath.
    • priority – задает приоритет шаблона, который учитывается при разрешении конфликтов шаблонов. Значением этого атрибута должно быть реальное число (положительное или отрицательное). При конфликте шаблонов (т.е. если исходному элементу соответствуют несколько шаблонов) применяется шаблон с наивысшим приоритетом.
    • mode – задает режим. Режимы позволяют обрабатывать элемент несколько раз, получая каждый раз другой результат. Подробнее режимы будут сказано при рассмотрении инструкции xsl:apply-templates .
    • name – задает имя шаблона, которое может быть использовано в инструкции xsl:call-template . Если элемент xsl:template содержит атрибут name , то атрибут match не является обязательным.

    Внутри элемента xsl:template задаются инструкции (правила) шаблона и фиксированные конечные элементы.

    Встроенные шаблоны

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

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

    Встроенный шаблон для текстовых узлов и узлов атрибутов просто копирует текст:

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

    Если в конечное дерево необходимо включить инструкцию обработки или комментарий, то для этого используются специальные инструкции xsl:processing-instruction и xsl:comment . Следует особо отметить одну важную особенность: если для элемента не указан шаблон, то будет применен встроенный шаблон, в соответствии с которым и сам элемент и все его потомки будут обработаны соответствующим образом. Но если для элемента задан шаблон, то его потомки войдут в конечное дерево, только если в шаблоне содержится инструкция xsl:apply-templates . Встроенный шаблоны обрабатываются так, как будто они были неявно импортированы прежде стиля, а потому имеют меньший приоритет импорта, чем все остальные шаблоны. Таким образом, пользователь может переопределить шаблон по умолчанию, явно включив новый шаблон.

    Инструкции или правила шаблона

    Инструкции или правила шаблона задаются внутри элемента xsl:template , и отдают процессору указание выполнить определенное действие (преобразование) над исходным элементом. Результат этого действия включается в конечное дерево. Задаются инструкции с помощью следующих элементов:

    • xsl:apply-templates
    • xsl:call-template
    • xsl:element
    • xsl:attribute
    • xsl:text
    • xsl:processing-instruction
    • xsl:comment
    • xsl:copy
    • xsl:value-of
    • xsl:copy-of
    • xsl:number
    • xsl:for-each
    • xsl:if
    • xsl:choose
    • xsl:when
    • xsl:otherwise
    • xsl:sort
    • xsl:message

    Фиксированные конечные элементы

    Помимо инструкций в шаблоне могут содержаться и другие элементы, не относящиеся к пространству имен XSL (т.е. не являющиеся инструкциями XSL), а введенные пользователем. Как правило, это теги HTML, но не только. По сути, пользователь может включить в шаблон любые элементы с одним ограничением: каждый из них и все они в целом должны соответствовать правилам XML, ведь xsl-документ является xml-документом. Такие элементы, введенные пользователем, получили название фиксированные конечные элементы. Называются они так потому, что переносятся в конечное дерево без каких-либо изменений. Их содержимым (т.е. потомками) могут являться как другие фиксированные конечные элементы, в том числе текстовые (т.е. просто текст), так и инструкции XSL. Инструкции в этом случае, как обычно, будут обрабатываться процессором, а фиксированные конечные элементы просто переноситься в него без изменений.

    Шаблон значения атрибута

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

    Основные команды XSLT

    Читайте также:

    1. A) Основные термины и определения
    2. Borland C и его основные режимы с характерными окнами
    3. D. Основные принципы.
    4. I. Основные права граждан
    5. I. Основные правила и принципы переноса слов
    6. II ОСНОВНЫЕ ПРАВИЛА МЕР БЕЗОПАСНОСТИ
    7. II. Основные понятия
    8. II.3.3. Основные направления денежно-кредитной политики
    9. III. Основные задачи и функции поисково-спасательных формирований ПСС МЧС России.
    10. III.2. Основные методы и критерии разрешения педагогических конфликтов
    11. V1: Предмет, метод и основные категории статистики как науки
    12. XIV. Основные понятия и методы математической статистики.

    xsl:apply-templates — Применение XSLT шаблона


    Атрибуты: select — расширенное X-Path выражение (опционально). Текстовое содержание отсутствует.

    Описание: Команда рекурсивно вызывает XSLT шаблон xsl:template с атрибутом match, совпадающим с X-Path выражением select, для всех потомков текущего XML узла, соответствующих данному выражению. Если атрибут select не задан, для каждого потомка текущего XML узла рекурсивно будет вызываться соответствующий XSLT шаблон xsl:template.

    Практика XSLT

    Пример трансформации XML-документа в HTML

    XSLT — это мощное средство для трансформации XML-данных. Его часто используют как web-шаблонизатор: на вход подаётся XML-документ и XSLT-преобразование, а на выходе получают HTML-документ. Процесс получения HTML-документа из XML называют отображением или рендерингом.

    Рассмотрим типичный пример рендеринга HTML.

    Дан список музыкальных композиций в виде XML-документа.

    Отобразим данный документ в виде HTML ul/li списка, как это показано ниже:

    Для этого используем следующее XSLT-преобразование:

    Данное преобразование вернёт нам следующий HTML:

    XSLT-преобразование состоит из трёх шаблонов ( xsl:template ). Каждый шаблон обслуживает свою сущность, что даёт нам возможность легко вносить изменения и делает код понятным.

    Если нам надо поменять отображение списка (например, добавить атрибут class), то мы редактируем шаблон match=»PlayList» .

    Если же мы хотим изменить отображение элементов списка, то тут, совершенно очевидно, что стоить менять шаблон match=»Track»

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

    Конечно, в более сложных случаях разделения добиться такого разделения бывает сложно. Очень легко прийти к ситуации, когда возникает «божественный шаблон», который делает всё, так же стоит бояться скатиться к «стрельбе дробью» кучей мелких шаблонов.

    Отладка XSLT

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

    Например, отладка поможет увидеть, что за сущность обрабатывает шаблон match=»/» .

    В Visual Studio отладка XSLT запускается сочетанием клавиш ALT+F5.

    Добавив в окно Watch XPath выражение » . » (точка), мы увидим, что текущий элемент шаблона — это корень (Root) документа. Здесь можно разместить контейнер div, или что-то относящееся ко всему XML-документу.

    Работа с сущностями XML

    Можно заметить, что в приведенных примерах присутствует сущность — Мы можем ее использовать, потому что определили ее в начале XSLT-документа

    Таким образом, — выводится, как символ с кодом — .

    Если нужно вывести строку «как есть», то стоит использовать CDATA следующим образом:

    Элемент xsl:text

    Хочу заострить внимание на элементе xsl:text . Он позволяет контролировать, что именно будет содержать TEXT-элемент. Значимость xsl:text очевидна на практике:

    Как видно из примера выше, отсутствие элемента xsl:text привело к появлению в HTML лишних переводов строк и пробелов.


    Безусловно, можно писать XSLT и без xsl:text , следующим образом:

    Такой шаблон трудночитаем и есть большая вероятность, что при сопровождении в нём будут появлятся ошибки.

    Нужно стараться, чтобы форматирование XSLT-шаблона не влияло на результат трансформации. Именно поэтому я считаю, что использовать xsl:text — это хорошая практика.

    Ветвления

    Для ветвлений в XSLT есть специальные элементы: xsl:if и xsl:choose . Но я считаю, что этими инструментами сильно злоупотребляют. Более интересен приём, позволяющий не загромождать шаблон ветвлениями.

    Рассмотрим пример реализации ветвлений:

    Дополним предыдущий пример возможностью выводить сообщение «Список пуст» в случае, если PlayList не содержит элементов Track .

    Решение с использованием xsl:choose будет таким:

    Решение с использованием дополнительного шаблона будет следующим:

    Второе решение, на мой взгляд, выглядит красивее: новая функциональность не добавила нового кода в старые шаблоны, новый шаблон максимально изолирован.

    Если понадобится добавить картинку к сообщению о пустом списке, то в первом случае скорее всего разбухнет элемент xsl:when в шаблоне match=»PlayList» . А вот во втором случае изменения будут только в специализированном шаблоне.

    В предыдущем примере мы разделили две абсолютно разные ветки рендеринга элемента списка. Но что если ветки различаются незначительно? Здесь использование xsl:if и xsl:choose вполне оправдано. Но мне бы хотелось показать другой подход: использование параметра mode у элемента xsl:template .

    В следующем примере навесим разные стили на чётные и нечётные элементы списка.

    Циклы и сортировка в XSLT

    Для циклов в XSLT есть элемент xsl:for-each , но схожий эффект можно получить, используя обычный xsl:apply-templates .

    Выведем список композиций, отсортированный по длительности.

    Вариант с использованием xsl:for-each :

    Вариант с использованием xsl:apply-templates :

    Как видно из кода, первый вариант короче и проще, но он нарушил принцип разделения ответственности для шаблонов. Теперь шаблон match=»PlayList» стал содержать логику отображения элемента Track.

    Казалось бы, ничего страшного, но представим задачу, когда в списке встречаются композиции с Id и без. Для композиции с ID нужно отрендерить ссылку, а для остальных вывести только текст.

    Вариант с использованием xsl:for-each :

    Вариант с использованием xsl:apply-templates :

    В случае xsl:for-each нам потребовалось добавлять ветвление, а в случае xsl:apply-templates — новый шаблон.

    Если бы шаблон match=»PlayList» уже содержал ветвления и логику, то нам понадобилось некоторое время, чтобы разобраться, куда именно нам нужно вставить ветку. Вариант с xsl:apply-templates лишён этого недостатка, поскольку мы лишь декларируем новый шаблон, а не пытаемся внедриться в старые.

    Использование xsl:for-each имеет ещё одну большую опасность. Если вы видите произвольный участок кода внутри шаблона match=»PlayList» , то предполагаете, что текущий элемент это PlayList , однако xsl:for-each меняет контекст. Увидев следующий код код:

    Вам потребуется внимательно присмотреться к контексту, чтобы понять, что select=».» на самом деле выбирает текущий Track .

    Шаблон mode=»TrackName» match=»Track» был добавлен для избежания дублирования кода, отображаюшего название. Я не сделал этого раньше, потому что в этом не было необходимости. Как только я заметил дублирование, я провёл рефакторинг и вынес общую логику отображения в новый шаблон.


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

    Заключение

    XSLT — это достаточно гибкий инструмент, он даёт возможность решить вашу задачу разными путями. Однако, при написании XSLT стоит уделять особое внимание сопровождаемости шаблонов.

    Надеюсь мои практические советы помогут вам писать более понятный код.

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

    Об XSLT шаблонизаторе

    Обращаюсь к всезнающему Олу!

    Встал вопрос разделить html на представление и данные. На википедии написано, что XSLT помогает разделить представление от данных, или я не правильно понял?

    Насколько выбор XSLT оправдан, по сравнению с CTemplate или CTPP?

    С уважением, Дмитрий.

    От: Lloyd
    Дата: 15.10.08 14:24
    Оценка:

    Здравствуйте, , Вы писали:

    А>Насколько выбор XSLT оправдан, по сравнению с CTemplate или CTPP?

    Не оправдан. Лучше возмите что-нить другое для этого.

    От: Кремер Евгений
    Дата: 15.10.08 15:02
    Оценка: 1 (1)

    Здравствуйте, Аноним, Вы писали:

    А>Встал вопрос разделить html на представление и данные. На википедии написано, что XSLT помогает разделить представление от данных, или я не правильно понял?

    А>Насколько выбор XSLT оправдан, по сравнению с CTemplate или CTPP?

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

    Для меня было бы совершенно очевидно решение «за» если
    1. Исходные данные уже в XML
    2. Трансформация будет проводится не часто, для генерирования в целом статичного контента, который при желании можно было бы в любой момент заново сгенерировать
    3. Если трансформировать часто то необходимо позаботиться о кешировании (как xslt так и выходных документов

    Конечно хслт это не язык программирования, но при использовании хслт 2 многое становится элементарным.

    От: Lloyd
    Дата: 15.10.08 15:06
    Оценка:

    Здравствуйте, Кремер Евгений, Вы писали:

    КЕ>Для меня было бы совершенно очевидно решение «за» если
    КЕ>1. Исходные данные уже в XML
    КЕ>2. Трансформация будет проводится не часто, для генерирования в целом статичного контента, который при желании можно было бы в любой момент заново сгенерировать
    КЕ>3. Если трансформировать часто то необходимо позаботиться о кешировании (как xslt так и выходных документов

    В чем будет преимущество xslt?

    От: Кремер Евгений
    Дата: 15.10.08 17:09
    Оценка:

    Здравствуйте, Lloyd, Вы писали:

    L>Здравствуйте, Кремер Евгений, Вы писали:

    КЕ>>Для меня было бы совершенно очевидно решение «за» если
    КЕ>>1. Исходные данные уже в XML
    КЕ>>2. Трансформация будет проводится не часто, для генерирования в целом статичного контента, который при желании можно было бы в любой момент заново сгенерировать
    КЕ>>3. Если трансформировать часто то необходимо позаботиться о кешировании (как xslt так и выходных документов

    L>В чем будет преимущество xslt?

    У меня нет желания ввязываться в спор, но для трансформации из хмл это на мой взгляд удобнейший инструмент:
    1. имеет набор операторов, которые заточены на рекурсивную работу с хмл;
    лаконичный XPath для выборки данных;
    возможности хслт 2 в особенности
    — RegExp,
    — последовательности,
    — встроенная группировка данных,
    — множества: пересечения, объединения, разность

    2. готовый стайлшит воспринимается понятнее, тк не содержит мусора (echo, print), взамен конечно другой мусор ( и т.п)
    но хслт мусор выглядит однообразнее со входными данными;
    3. хслт решение в моих случаях было лаконичнее;
    4. хмл входит в нашу программисткую жизнь все больше и больше и хслт часть него, полезно бы иметь опыт работы с ним

    Спору нет хслт медленный в сравнении с кодом который читает хмл кас строки делает соответствующие замены. Но если хмл загружается (строится DOM) и просто обрабатывается конструкциями selectNodes() и подобными, то скорости обработки можно считать равными (опять же зависит от размера хмл). Зато читать такой код будет одно мучение. К сожалению не знаком с Шаблонизаторами для хмл, но если таковые существуют и стоили бы того, то уже давно бы вытеснили хслт.

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

    PS: В свое время я тоже скептически относился к хмл! Главное знать где и как применять. И я ни в коей мере не агитирую к повсеместному применению хмл и хслт.

    Мастер Йода рекомендует:  Стандартным поиском на смартфонах на базе WP8 для России и СНГ станет Яндекс
Добавить комментарий