« Поставить закладку » « Сделать стартовой »

« Форумы » « Блоги » « Статьи » « Новости » « Файлы » « Realcoding IRC » « Site map » « Поиск »


Главная Главная
Анонсы Анонсы
Форумы Форумы
Каталог Каталог
Поиск Поиск
Опросы Опросы
Книжный магазин Книжный магазин
Реклама на сайте
Публикации Публикации
Партнеры Партнеры
Карта Карта сайта
Рассылки Рассылки
RSS экспорт
Настройки Настройки
О нас пишут О нас пишут
Контакты Контакты
Гостевая книга Гостевая книга


ПнВтСрЧтПтСбВс
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31        
    Популярное
Использование переключателей для управления выводом

Автоматическая обработка ошибок

Структурирование и классификация проекта

Если бы программисты строили дома...

Функция AccessResource

Использование компонента StringGrid

SQL Server: основные концепции для администраторов Windows

Работа с Bluetooth в Delphi. Передача данных через Bluetooth

CVS - система управления версиями

Remote Data




    Архив файлов



    Сообщества

    Документация

    Кто на сайте
Вы не зарегистрированы.
Имя:

Пароль:

Запомнить

Регистрация позволит Вам пользоваться дополнительными сервисами.
Сейчас на сайте:
Гостей: 81
Пользователей: 0

Статьи:: Интернет технологии :: XML :: Практический XSLT. Использование в качестве шаблонизатора



отправить ссылку другу версия для печати  Обсудить на форуме

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

Автор: Fade
Источник: habrahabr

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

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

Рабочий стол

Определим, что нам нужно для работы:
  • Входной XML-документ
  • XHTML-макет шаблона
  • Парсер XML для склейки XML с XSL

У меня входной XML документ выдает CMS-система, в которой каждая страница с материалом собирается в XML-дерево.

К XHTML-макету никаких ограничений нет. Есть лишь определенные рекомендации по верстке, которые позволят значительно сэкономить время на формирование шаблона.

В качестве парсера (сборщика) конечного документа можно использовать браузер. Нужно лишь указать в XML-документы путь к файлу шаблону:
<?xml-stylesheet type="text/xsl" href="template.xsl" ?>

Хотя, как показала практика, этот механизм довольно глючный (мне пришлось пользовать IE). Лучше воспользоваться средствами XML-парсинга языка, на котором написана CMS-система. Я использую Parser (на нем, вообщем-то, у меня вся система и работает).

Входной XML-документ

Для начала разберемся со входным XML-документом. Для того, чтобы использовать XSL нужно иметь полное представление о его структуре.

Я использую следующую схему:

<?xml version="1.0" encoding="windows-1251"?>
<document lang="ru" id="0">
<header>
<title>Начало</title>
</header>
<lang_table>
<item hit="yes" lang="ru" title="Russian"/>
</lang_table>
<navigation>
<sections>
<item id="0" parent_id="0" is_published="1" section="1">
<title>Начало</title>
<dir>/</dir>
</item>
<item id="1" parent_id="0" is_published="1" section="1">
<title>Новости</title>
<dir>news</dir>
</item>
</sections>
</navigation>
<content>
<item id="1" container="1" sorting="2" type="com" method="list_news" title="Новости"></item>
</content>
</document>

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

<?xml version="1.0" encoding="windows-1251"?> - заголовок XML-файла. Должен идти строго с начала файла. В нем прописана версия используемого XML-языка и кодировка документа. Я как правило работаю в windows-1251 (пока так удобнее), но, по идее UTF-8 лучше.

<document lang="ru" id="0"> - корневой элемент документа (можно придумать свое имя). Атрибуты:
  • Lang - язык документа. Нужен для создания мультиязычных шаблонов.
  • Id - идентификатор текущего раздела.

<lang_table> - таблица языков, используемых на сайте.
<navigation> - блок элементов навигации:
<sections> - блок основной навигации (основная структура сайта):
<item id="0" parent_id="0" is_published="1" section="1"> - элемент структуры сайта. Атрибуты:
  • Id - идентификатор раздела.
  • Parent_id - идентификатор родительского раздела.
  • Is_published - опубликован ли раздел.
  • Dir - uri-адрес раздела. По нему формируются полные адреса.
  • Section - тип раздела. Используется если необходимо разбить меню на основное и сервисное.

<content> - блок содержимого.
В моей CMS используется модульная структура: все наполнение сайта представляет собой модули двух видов:

  • Html - текстовый модуль. Статические модули, которые заполняет редактор сайта.
  • Com - модуль-компонента. Динамические модули, которые формируют различные программные модули CMS: новости, статистика, поисковые блоки и т.д.

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

CMS при сборке страницы просто выводит в все модули, которые задействованы на странице в виде: <item id="1" container="1" sorting="2" type="com" method="list_news" title="Новости">
Атрибуты:
  • Id - идентификатор модуля.
  • Container - блок-назначение (в каком блоке шаблона выводиться).
  • Sorting - порядок вывода в блоке.
  • Type - тип:
    • Com - модуль-компонентаю
    • Html - текстовый модуль.

  • Method - обработчик данных.
  • Title - название модуля.

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

<!DOCTYPE site_page [
<!-- Character entity references for ISO 8859-1 characters -->
<!ENTITY nbsp "&#160;">
<!ENTITY sect "&#167;" >
<!ENTITY copy "&#169;">
<!ENTITY laquo "&#171;">
<!ENTITY reg "&#174;">
<!ENTITY deg "&#176;">
<!ENTITY plusmn "&#177;">
<!ENTITY para "&#182;">
<!ENTITY raquo "&#187;">
<!ENTITY times "&#215;">

<!-- Character entity references for symbols, mathematical symbols, and Greek letters -->

<!ENTITY bull "&#8226;">
<!ENTITY hellip "&#8230;">

<!-- Character entity references for markup-significant and internationalization characters -->

<!ENTITY ndash "&#8211;">
<!ENTITY mdash "&#8212;">
<!ENTITY lsquo "&#8216;">
<!ENTITY rsquo "&#8217;">
<!ENTITY sbquo "&#8218;">
<!ENTITY ldquo "&#8220;">
<!ENTITY rdquo "&#8221;">
<!ENTITY bdquo "&#8222;">
<!ENTITY lsaquo "&#8249;">
<!ENTITY rsaquo "&#8250;" >
<!ENTITY euro "&#8364;">
]>

Его можно вставить прямо в XML-документ. Сразу после <?xml version="1.0" encoding="windows-1251"?>.

Подготовка XHML-шаблона


XSL-шаблон создается на базе XHTML-шаблона (некой типовой страницы сайта). Код XHTML-страницы, при этом, должен быть валидным.

Рассмотрим по шагам процесс создания шаблона.

Проверив валидность XHML-страницы своего шаблона, для облегчения собственной работы, обозначьте в нем положение всех динамических блоков:
  • Меню (и других элементов навигации).
  • Информационных блоков страницы - то место в шаблоне, в котором будут выводиться модули сайта.
  • Заголовка/названия страницы.

Сделать это лучше всего с помощью обычных HTML-комментариев:
...
<h1 class="top">
<!-- Название раздела -->
Администрирование сайта
<!-- /Название раздела -->
</h1>
...
<!-- меню -->
<ul id="main-menu">
<li><a href="#">Начало</a></li>
<li class="curent-item"><a href="#">Новости</a></li>
<li><a href="#">Разделы</a></li>
</ul>
<!-- /меню -->
...
<!-- блок левых модулей -->
Всякие новости
<!-- /блок левых модулей -->
...
<!-- Блок основного содержимого -->
Текст
<!-- /Блок основного содержимого -->
...


Основы описания XSL-шаблонов


Все файлы XSL-шаблонов имеют следующий вид:
<xsl:stylesheet version = `1.0` encoding="UTF-8"?>
<xsl:template match="element">
данные шаблона
</xsl:template>
</xsl:stylesheet>


Где: <xsl:stylesheet version = `1.0` encoding="UTF-8"?> - определяет тип XML-документа и кодировку. Я использую UTF-8 (не спрашивайте, почему).
<xsl:stylesheet> </xsl:stylesheet> - начало и конец XSL-документа.
<xsl:template match="element"> </xsl:template> - начало и конец шаблона для элемента element.

Шаблоны можно условно разделить на три вида:
  • <xsl:template match="element"></xsl:template> - шаблон, описывающий правила преобразования элемента element. Применяется автоматически ко всем элементам element.
  • <xsl:template match="element" mode="mode1"></xsl:template> - шаблон, описывающий правила преобразования элемента element в режиме mode1. Таким образом можно описать различные правила обработки элементов element.
  • <xsl:template name="template-name"></xsl:template> - шаблон с именем template-name. Не имеет привязки к какому-либо элементу XML-документа.

Если элементы одного вида могут встречаться в различных частях структуры XML-документа (например, в XML-документе, формируемом системой элемент item используется повсеместно и имеет разное значение), то в шаблоне можно указать "структурный адрес" такого элемента:
<xsl:template match="navigation/sections/item"></xsl:template>
При этом, порядок применения шаблонов иерархичный, т.е., сначала шаблон применяется к корневому элементу, а затем, к дочерним, т.е. если мы вызвали обработчик для navigation, то для вызова обработчика для navigation/sections/item нам достаточно указать адрес sections/item.

Структура папок шаблонов


Для того, чтобы хранить на одном сайте несколько модулей необходимо как-то продумать структуру их хранения в папкам. При этом, удобнее разбить шаблоны на модули по нескольким xsl-файлам. Такой подход позволит в дальнейшем повторно их использовать при создании новых шаблонов.

В простейшем варианте можно создать каталог xsl и там все складировать.

Далее, чтобы внутри этого каталог шаблоны не путались (для каждого шаблона у нас получиться несколько файлов) создадим вложенные каталоги:
  • template_folder - каталог с файлами шаблона. Называть ее можно по имени шаблона, например my_template.
  • dtd - файлы описания основных сущностей. Могут быть полезными.
  • lang - шаблоны сообщений для различных языков (если на сайте используется их используется несколько).
  • mod - шаблоны модулей.

Нам для начала потребуется создать каталог xsl/my_template и в нем, файл layout.xsl следующего вида:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xsl:stylesheet SYSTEM "../dtd/entities.dtd">
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!-- Основной шаблон -->
<xsl:template match="/node()">
</xsl:template>
<!-- / Основной шаблон -->
</xsl:stylesheet>

Где:
<xsl:template match="/node()"> </xsl:template> - шаблон для элемента /node() (корневого). Вместо /node() можно указать //document, т.к. он у нас являеться корневым узлом.

Копируем весь XHTML-код внутрь блока <xsl:template match="/node()"></xsl:template>

Этот шаблон будет автоматически применяться ко всему XML-документу. В нашем случае, XSL-преобразование заменит весь XML-код на XHTML-код вашего шаблона.

Далее, необходимо в директории XSL создать файл template.xsl (где, template - название вашего шаблона), в котором размещаем следующий код:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!-- общий файл шаблона -->
<xsl:import href=" my_template /layout.xsl"/>
</xsl:stylesheet>

Где:
<xsl:import href="my_template/layout.xsl"/>
Директива импорта внешнего XSL-файла (обрабатываеться XSL-процессором) из указанного файла. Путь к файлу указываем относительный.

Создание шаблона для основного навигационного меню


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

Следующий шаг - создание шаблона для меню.

Меню навигации сайта строиться на основе его структуры, представленной в XML-документе в следующем виде:
<navigation>
<sections>
<item id="0" parent_id="0" is_published="1" section="1">
<title>Начало</title>
<dir>/</dir>
</item>
<item id="1" parent_id="0" is_published="1" section="1" hit="yes">
<title>Новости</title>
<dir>news</dir>
</item>
</sections>
</navigation>

Текущий раздел определяется по двум параметрам:
  • Атрибуту id у корневого элемента document - он всегда равен id текущего раздела.
  • Атрибуту hit у элемента item - если таковой имеется, то это значит, мы находимся на "главной странице раздела".

Соответственно, для того, чтобы вывести меню сайта необходимо создать шаблон для элементов:
  • sections - корневой элемент меню.
  • item - элемент меню.

При этом, необходимо учесть, что элементы item могут содержать другие элементы item, в том случае, если у раздела есть подразделы:
<item>
<item></item>
</item>


1. Создаем в директории xsl/my_template файл navigation.xsl следующего вида:


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xsl:stylesheet SYSTEM "../dtd/entities.dtd">
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!-- Глобальное меню навигации -->
<xsl:template match="sections" mode="global_menu">
</xsl:template>
<!-- /Глобальное меню навигации -->
</xsl:stylesheet>


2. Вставляем в шаблон код нашего меню из файла layout.xsl:


<!-- Глобальное меню навигации -->
<xsl:template match="sections" mode="global_menu">
<ul id="main-menu">
<li class="curent-item"><a href="/">Начало</a></li>
<li><a href="/sections/">Разделы</a></li>
<li><a href="/news/">Новости</a></li>
</ul>
</xsl:template>
<!-- /Глобальное меню навигации -->


3. …а на его место в файле layout.xsl вставляем вызов нашего шаблона меню:


<!-- меню -->
<xsl:apply-templates select="navigation/sections" mode="global_menu"/>
<!-- /меню -->

Где:
select="navigation/sections" - относительный (относительно текущего) путь-адрес элемента. При этом, будут обработаны все элементы navigation/sections.

mode="global_menu" - используем шаблон с режимом global_menu. Это нам нужно на тот случай, если нужно будет выводить еще и сервисное меню, отдельно, или "хлебные крошки", или что-еще другое на основе одной и той же ветки навигации.

4. Плюс, добавим в файл layout.xsl директиву импорта файла шаблона navigation.xsl:


<xsl:import href="navigation.xsl"/>

5. Далее, создаем в файле navigation.xsl еще один шаблон, для обработки пунктов меню:


<!-- Обработка ссылок меню -->
<xsl:template match="item" mode="global_menu">
<li>
<a>
<xsl:call-template name="href_attribute"/>
<xsl:value-of select="title"/>
</a>
</li>
</xsl:template>
<!-- /Обработка ссылок меню -->

Где:
<xsl:call-template name="href_attribute"/> - вызов шаблона по имени. При этом шаблон не имеет привязки к элементу, т.е. вызывается произвольно.

<xsl:value-of select="title"/> - вставка-вывод значения элемента title текущего элемента. Если в параметре перед именем элемента поставить символ @ - выводиться будет значения атрибута текущего элемента.

6. Немного изменяем шаблон sections:


<!-- Глобальное меню навигации -->
<xsl:template match="sections" mode="global_menu">
<ul id="main-menu">
<xsl:apply-templates select="item" mode="global_menu"/>
</ul>
</xsl:template>
<!-- /Глобальное меню навигации -->

Где:
<xsl:apply-templates select="item" mode="global_menu"/> - обработка всех элементов item элемента sections. При этом, элементы item самих элементов item (sections/item/item) обрабатываться не будут, т.е. выводиться только один уровень меню разделов.

Мы вынесли обработку элементов item (пунктов меню) в отдельный шаблон. При этом, в нем мы добавили еще и вызов другого шаблона: <xsl:call-template name="href_attribute"/>

Этот шаблон будет формировать нормальные uri-ссылки для элементов нашего меню. О нем немного позже.

7. Теперь нам необходимо доделать меню,


чтобы оно учитывало, какой раздел является текущим. Для этого нам придется добавить условную обработку в наш шаблон элемента item:
<!-- Обработка ссылок меню -->
<xsl:template match="item" mode="global_menu">
<li>
<xsl:choose>
<!-- если Текущий раздел -->
<xsl:when test="descendant-or-self::*/@id = /node()/@id">
<xsl:value-of select="title"/>
</xsl:when>
<!-- если раздел не текщий -->
<xsl:otherwise>
<a>
<xsl:call-template name="href_attribute"/>
<xsl:value-of select="title"/>
</a>
</xsl:otherwise>
</xsl:choose>
</li>
</xsl:template>
<!-- /Обработка ссылок меню -->

Здесь мы сталкиваемся с новой конструкцией:
<xsl:choose>
<xsl:when></xsl:when>
<xsl:otherwise></xsl:otherwise>
</xsl:choose>

…которая, собственно, и задает условную обработку XML-элементов. В качестве параметра мы задаем условие: <xsl:when test="descendant-or-self::*/@id = /node()/@id">

В нашем случае это условие равенства атрибутов ID у корневого элемента (document) и текущего элемента (item), которое и определяет, является ли элемент текущим.

Внутри блока <xsl:when></xsl:when> располагается то, что выводиться в случае выполнения условия. В блоке <xsl:otherwise></xsl:otherwise> - если условие не выполняется.

8. Теперь, разберем шаблон href_attribute:


<!-- Обработка адреса ссылок меню -->
<xsl:template name="href_attribute">
<xsl:attribute name="href">
<xsl:text>/</xsl:text>
<xsl:for-each select="ancestor-or-self::item">
<xsl:value-of select="dir"/>
<xsl:text>/</xsl:text>
</xsl:for-each>
</xsl:attribute>
</xsl:template>
<!-- /Обработка адреса ссылок меню -->


Здесь мы сталкиваемся с инструкцией xsl:attribute. Она позволяет создавать атрибуты для элементов внутри которого она вызывается. В нашем случае мы вызываем ее из элемента a, соответственно, она создаст для него атрибут href, т.е. адрес.

Инструкция <xsl:for-each select="ancestor-or-self::item"> задает цикл обработки для всех элементов, удовлетворяющих условию. В нашем случае мы выбираем ancestor-or-self::item - ось элементов от корневого элемента до текущего по цепочке. В нашем случае это позволяет выбрать для всей цепочки узлы dir, т.е. построить полный адрес текущего узла-раздела.

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



Рубрика: XML




Вышел MySQL 5.1.30, первый стабильный рели....

MySQL

После публикации 29 тестовых версий анонсирован первый стабильный релиз MySQL 5.1, пригодный для промышленной эксплуатации и обеспечивающий увеличение производительности для "тяжелых" SQL запросов, по сравнению с MySQL 5.0, примерно на 15-20%. Главные новшества появившиеся в MySQL 5.1:


Подробнее... | Рубрика: MySQL | Добавлено: 28.11.2008

Тестирование параллельных программ.

Тестирование

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


Подробнее... | Рубрика: Тестирование | Добавлено: 28.11.2008

Архитектура AMD64 (EM64T).

Архитектура AMD

Аннотация. В статье кратко рассматривается архитектура AMD64 компании AMD и ее реализация EM64T компании Intel. Описаны особенности архитектуры, ее возможности, достоинства и недостатки.


Подробнее... | Рубрика: Архитектура AMD | Добавлено: 27.11.2008

Остальные статьи:

Платформа 2009. Определяя будущее
Windows Vista Bridge Sample Library - упра...
Оптимизация 64-битных программ
Подгрузка через AJAX HTML-кода, содержащег...
Обзор нового релиза самой мощной Ajax библ...
Firebug 1.3 и 1.4 alpha — что нового и инт...
Релиз Microsoft Silverlight 2.0. Что новог...
XML документация в C#
Курсоры в MySQL 5
Microsoft опубликовала подробности о сесси...
Microsoft делится подробностями о том, что...
Тестируем новый javascript от нового брауз...
MySQL Query Cache
Использование провайдеров компиляции в As...
Чего мы ждем от C# 4.0
Delphi 2009 и C++Builder 2009
Джоэл Спольски и Джеф Этвуд запустили новы...
Поиск кода Google /* что нового? */
10 jQuery скриптов для улучшения интерфейс...
Генераторы отчетов FastReport 4 и QuickRep...


Цитата дня (все,добавить):

Портал фрилансеров

работа на дому


    Рубрикатор

Программирование

C/С++
Обучение
Windows API
XAML
Моделирование
Паттерны
Visual Basic 7 .NET
WxWidgets
Функции WinApi
Функции С++
Разработка под Mac OS
Eiffel
Visual Studio 2008
UI дизайн
Алгоритмы
Конкурсные статьи
Turbo Pascal
Visual Studio
CASE-средства
Visual Studio 2005
Без VCL
Delphi
Тех. документация
Тестирование
Software Testing
ООП
TCP/IP
Google Android
Windows Installer
.NET Framework
Драйвера
C# C Sharp
Справка
Проектирование
Информ. системы
Visual Basic
Assembler
Оптимизация кода
Gtk+
Компоненты
Реинжиниринг
Управление проектами
Extreeme programming
Lotus Notes
Алгебраическое проектирование


Интернет технологии

PHP
Perl
ASP
WAP
Cookies
SSI
CGI
Web Servers
VB Script
DNS
CSS
XML
Html
Java Script
Java2ME
Firewall
Flash
.htaccess
Apache
VRML
Протоколы
Поисковые системы
Технология JAVA
Учебник по PHP
Учебник по JavaScript
Учебник по XML
Java Q&A
AJAX
DHTML
XHTML
Dreamweaver
Web 2.0
Python
Вебмастеру
Cisco
Ruby on Rails
Silverlight

Базы данных

Access
InterBase
MySQL
Oracle
ADO .NET
Основы SQL
Учебник по Access 2002
MS
Microsoft FoxPro
Доступ к данным
XML в MS SQL Server 2000
ODBC и MyODBC
Обучение
Caché
DB2
PostgresSQL
Sybase
Теория
Хранилища данных
Безопасность
Реляционные данные
MySQL и mSQL

Остальное:

Разное
Обзоры книг
Безопасность
Графика и дизайн
Юмор
Linux
Фракталы
Microsoft Axapta
Многоядерность
Сети
Microsoft Office
Работа
MS-DOS
Криптография
Графика и игроделание
Новости SDK
Системы защиты
Учебник по AutoCad
CVS
Windows XP
Windows Server 2003
Windows Vista
Windows 7
Мероприятия