Журнал LinuxFormat - перейти на главную

LXF91:XSLT

Материал из Linuxformat
Перейти к: навигация, поиск
Изучаем XSLT Превращаем RSS, фотоальбомы и многое другое, хранящееся в XML, в удобные web-страницы.

Содержание

XSLT: Создадим таблицу стилей

Мозги у вас на месте, а как с внешним видом? Умело оформив RSS, вы получите призы в обеих номинациях. А поможет вам в этом Рейчел Проберт.

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

  • Хочу «одолжить» ленту новостей с чужого сайта, но оформить ее в собственном стиле.
  • Не хочу, чтобы подписчики моей RSS-ленты видели в своих браузерах сырой XML, лучше создать нечто удобное для чтения.

Ответ на оба вопроса дает тема нашего занятия: XSLT.

Расширенный XML

Что же такое XSLT, и как мы будем им пользоваться? eXtensible Stylesheet Language Transformation или XSLT – это язык преобразования одних XML-документов в другие XML-документы. Он является подмножеством XSL, языка таблиц стилей XML. На данном уроке мы составим на XSLT таблицу стилей, «подгоняющую» существующую RSS-ленту к дизайну вашего сайта. Затем мы применим эту таблицу к исходному XML, чтобы пользователи могли просмотреть новости в человеко-читаемом виде.

Пользователям Firefox 2 или Internet Explorer 7 (фи) может показаться, что RSS-новости всегда выглядят неплохо. Дело в том, что новейшие браузеры воспроизводят RSS-ленты в удобочитаемом формате (независимо от наличия таблиц стилей в исходном коде), вместо бесхитростного отображения XML, как это было в недавнем прошлом. Но если у вас другой браузер (или версия), то при отсутствии таблицы стилей вы будете иметь несчастье созерцать «сырой» XML. Во врезке «Браузеры и RSS» приводится список браузеров, умеющих отображать RSS в приличном виде.

Образцы таблиц

Есть несколько фантастических примеров стилевых таблиц, в которых можно черпать вдохновение. Вот наиболее известные адреса:

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

LXF91 xslt1.png

Не надо громадного бюджета: просто освоим таблицы стилей!

Приступим

Наш проект можно разделить на четыре стадии. Мы возьмем RSS-ленту Linux с http://Digg.com, воспользуемся таблицей XSLT, преобразуем Digg XML в элегантный HTML и отобразим его. Для урока вам понадобятся некоторые навыки и парочка полезных программ. Прежде всего, позаимствуем на http://www.digg.com ленту новостей о Linux/Unix. Чтобы усвоить урок, пригодится знакомство с XML, но честно говоря, оно не обязательно: если вы сумеете разобраться в содержании RSS-файла, проблем не должно быть. Однако прежде чем знакомиться с XSLT, необходимо понять XPath.

XPath для XML – примерно то же, что SQL для реляционных баз данных. Основная задача XPath – идентификация частей, или узлов, XML-документа. Рассмотрим следующий пример XML-файла:

<fridge>
    <fish species=”trout” />
    <meat name=”ermintrude” />
    <fish name=”nemo” />
    <fish>wanda</fish>
 </fridge>

XPath-эквивалент для выражения SELECT fish FROM fridge можно записать как /fridge/fish. Подошло бы и //fish, но этот вариант вернет всю рыбу, как в холодильнике, так и вне его. У XPath много общего с файловой системой Linux, поэтому знаток командной строки без труда разберется в навигации: ../ приведет к узлу, расположенному сразу над текущим (./).

Можно запрашивать XML не только по названию тэга, но и по атрибутам (см. врезку «Выражения XPath»). Чтобы выбрать все компоненты холодильника, имеющие атрибут name (имя), можно воспользоваться выражением /fridge/*[@name]. Будут возвращены Nemo и Ermintrude, тогда как //fish[@*] вернет рыбу, имеющую хоть какой-то атрибут (всю, кроме Wanda). Можно указать //fish[@name=”nemo”], тогда будет выбрана рыба, атрибут name которой равняется Nemo.

Итак, XPath использует «путевые» выражения для выбора узлов или групп узлов в XML-документе. Узлы выбираются, следуя указанному пути или шагам.

Для желающих получить более глубокие знания по этой теме, а заодно и попрактиковаться, у Firefox есть замечательный модуль под названием XPather (http://xpath.alephzarro.com). Установив XPather, можно загрузить в Firefox XML-файл, щелкнуть в окне правой кнопкой мыши и выбрать в контекстном меню пункт Show In XPather (Открыть в XPather). Работая со сложными XML-файлами, вы сможете проверять в XPather, соответствуют ли возвращаемые узлы вашим ожиданиям.

Попробуем реальные примеры. Загрузите http://www.digg.com/rss/indexlinux_unix.xml в Firefox и откройте исходный код страницы. Скопируйте его в файл на жестком диске, затем откройте этот локальный файл в Firefox. Мы делаем это потому, что последние версии Firefox конвертируют RSS в HTML. Локальные файлы не конвертируются, так что откроем окно XPather. Сперва попытаемся найти заголовок RSS-канала. В окне ввода XPather наберите /rss/channel/title и нажмите кнопку Eval (Вычислить). Если все прошло гладко, результатом будет следующее значение: «Digg/Linux/Unix». Теперь испробуем //item/title – должны возвратиться 40 значений, отображающих заголовки всех статей данной ленты.

Последний шаг перед началом действительно сложной работы – это установка xsltproc, инструмента командной строки для обработки XML-документов с помощью таблиц XSLT. Это часть С-библиотеки XSLT для Gnome, способная, впрочем, работать и в отрыве от этого рабочего стола. Если ваш дистрибутив использует APT, просто наберите приведенную ниже строку; если нет – обратитесь за инструкциями об установке ПО к менеджеру пакетов своего дистрибутива.

sudo apt-get install xsltproc

Охота за контентом

В конечном итоге, мы будем иметь дело с тремя взаимосвязанными файлами: исходным XML, XSLT-таблицей, которую мы собираемся создать, и выходным HTML, преобразованным xsltproc (см. Рис. 2). Первый шаг – определение RSS-ленты, которую мы стилизуем под свой сайт. Вы уже знаете, что я выбрала канал Linux/Unix Digg на http://www.digg.com/rss/indexlinux_unix.xml.

Рис. 2

Волшебник xsltproc – ну как он это делает?

Потратьте некоторое время на изучение исходного XML-файла нашей ленты, это пригодится для создания XSLT-таблицы. Если ваш браузер воспроизводит ленты в читаемом формате, понадобится открыть исходный код выбором пункта контекстного меню View Page Source [Просмотр исходного кода страницы]. Этот-то файл нас и интересует. Наиболее важная для нас информация разделена на узлы: канал (channel), заголовок (title) и пункт (item). На данном этапе неплохо бы определить вид нашей страницы новостей. Подумайте, какие части вам хотелось бы включить и как они будут выглядеть.

Мясо, картошка и лук

Держите копию исходного кода RSS-ленты открытой, чтобы можно было быстро взглянуть на него в случае необходимости. Теперь войдите в свою рабочую директорию и создайте файл с названием digg.xsl. Откройте этот файл в любым текстовом редакторе, оказавшемся под рукой. Я работаю в Kubuntu и пользуюсь Kate… ну, это неважно.

Начнем нашу таблицу так:

 <xsl:stylesheet version=‘1.0’
 xmlns:xsl=’http://www.w3.org/1999/XSL/Transform’
 xmlns:digg=”http://digg.com/docs/diggrss/”>
 <xsl:output method=”html”/>
 <xsl:variable name=”title” select=”/rss/channel/title”/>

Таблица стилей XSLT начинается с элемента <xsl:stylesheet> и содержит операторы, управляющие воспроизведением. Мы должны также включить атрибут version=”1.0”.

Чтобы работать с элементами и атрибутами XSLT, в начале документа нужно объявить пространство имен XSLT (xmlns). Пространство имен XML – это метод разрешения конфликтов имен. В RSS есть предопределенные элементы, поэтому издатели вроде iTunes и Digg для удобства пользователей расширяют свои RSS-ленты дополнительными тэгами. Объявив пространство имен, мы получаем доступ к расширенным тэгам, образуя выражения объединением пространства имен с названием нового тэга через двоеточие (:), например digg:title. Тэг title входит в пространство имен digg, поэтому он не будет конфликтовать с тэгами, заранее определенными в XML-спецификации RSS. Мы начали с xmlns:xsl=”http://www.w3.org/1999/XSL/Transform, что указывает на пространство имен W3C для XSLT.

Скорая помощь

В мире Linux есть замечательное ПО для работы с XML. Взгляните на IDE Treebeard по адресу: http://treebeard.sourceforge.net/index.php.

В четвертой строке указан выходной формат 'html: ведь мы собрались построить HTML-файл! И последнее. Мы будем обращаться к заголовку канала неоднократно, поэтому, для экономии процессорного времени, установим переменную title, доступную в пределах всего нашего кода. Переменная title получает значение, возвращаемое выражение Xpath, заданное атрибутом select (/rss/channel/title). В нашем примере оно равняется Digg/Linux/Unix. Переменные доступны по нотации $title.

Итак, приправив наш документ лучком предписаний, начнем готовить мясо и картошку: элемент xsl:template (template – шаблон). Наберите

<xsl:template match=”/”>

Шаблон применяется ко всем узлам, отвечающим выражению Xpath, указанному в атрибуте match. Мы создаем HTML-документ, поэтому нам понадобится лишь один набор тэгов <html>. Следовательно, наш первый шаблон должен соответствовать только одному узлу. Можно было бы использовать любое выражение, возвращающее единственный узел, например “/rss” или “/rss/channel”, но вернее будет “/”, потому что такой узел грантированно один.

Пора задать разметку HTML-документа. Наберите следующее:

 <html>
 <head>
 <title><xsl:value-of select=”$title” /></title>
 </head>

Как вы уже заметили, заголовок страницы задается переменной $title. Нотация, которую мы используем для этого – элемент XSLT <xsl:value-of>. Элемент value-of работает как с переменными, так и с выражениями XPath.

Теперь добавьте

   <body>
   <div style=”width:250px; float:right; padding:10px; margin:10px; border:thin dashed lightgrey;”>
К чему это все? Это RSS-лента с сайта Digg. Благодаря полученным
навыкам работы с XSLT, новости с нее читаются и отображаются
довольно мило.<hr />Если вы написали собственную RSS-ленту и
предпочли бы включить ее вместо Diggs, можете использовать
данный контейнер для описания целевой аудитории и способа
подписаться на эту ленту.
</div>
Возможности стилизации шаблона поистине безграничны. Я поместила в контейнер
пояснения о содержании RSS и придала доку менту некоторый стиль и правила поведения с помощью CSS. Тэг
делит содержание страницы на логические блоки. Я хочу сказать, что
определяет секции, которыми легко управлять, манипулировать, менять их стиль и которые легко читать. Обратите внимание на то, как я стилизовала контейнер
, определив его положение, ширину, заполнение, границы и наличие рамки. Для творческого вдохновения, проанализируйте другие CSS.

Расставим по местам

Определив раскладку страницы, можно подумать о том, где применить шаблон. Попробуйте набрать следующее:

   <h1>Welcome to today’s <xsl:value-of select=”$title” /> News</h1>
   <xsl:apply-templates select=”rss/channel/item”/>
   <p>Пока это все, но мы скоро вернемся.</p>
   </body>
   </html>
   </xsl:template>

Мы опять, как видите, воспользовались элементом <xsl:value-of>, чтобы поместить заголовок на страницу. Затем мы применили элемент <xsl:apply-templates> для вызова второго шаблона и добавили атрибут select: он будет обрабатывать лишь те узлы, значения которых соответствуют заданному выражению – в нашем случае это все пункты в канале RSS-ленты, т.е. статьи новостей. Фактически, мы встроили все пункты канала в соответствующую секцию HTML-кода (считайте это функцией отображения). Наконец, чтобы удостовериться в правильности размещения шаблона, мы добавили завершающую часть страницы.

Теперь необходимо задать разметку для узлов channel/item (ста тей Digg). Так как критерий match нашего шаблона возвращает группу узлов (несколько узлов, или статей), шаблон применяется к каждому узлу из этой группы.

  <xsl:template match=”rss/channel/item”>

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

   <h2>
   <xsl:element name=”a”>
   <xsl:attribute name=”href”><xsl:value-of select=”./link” /></xsl:attribute>
   <xsl:attribute name=”target”>_new</xsl:attribute>

Выражение xsl:element служит для создания тэгов средствами XSLT. Уместен вопрос: почему бы не воспользоваться обычными гиперссылками HTML? Дело в том, что наши атрибуты href создаются динамически, а мы не можем поместить один XML-элемент в другой. Значит, нижеследующая строка просто не сработает:

  <a href=”<xsl:value-of select=”./link” />” target=”_new”>

Элемент xsl:attribute срабатывает лишь тогда, когда он попадает внутрь xsl:element, и используется для добавления атрибутов к тэгу, который мы конструируем.

У XSLT есть еще один «туз в рукаве». В русле продуктовой темы, это будет наш десерт. Речь идет об элементе xsl:if, работающем с функцией contains(). В XSLT больше сотни встроенных функций, покрывающих почти все ваши нужды. Хотите быть круче – можете встроить расширения с помощью своего любимого языка программирования (если процессор XSLT его поддерживает). Пользуясь xsl:if, давайте попробуем сделать вот что: если заголовок статьи Digg содержит слово «Linux», пусть он выводится красным цветом. Добавьте в код следующие строки:

  <xsl:if test=”contains(./title,’Linux’)>
  <xsl:attribute name=”style”>color:red;</xsl:attribute>
  </xsl:if>
  <xsl:value-of select=”./title” />
  </xsl:element>
  </h2>

Теперь можно воспользоваться элементом <xsl:value-of> и выбрать интересующие нас узлы:

  <strong>Published on: </strong><xsl:value-of select=”./pubDate”/><br />
  <strong>Number of Diggs: </strong><xsl:value-of select=”./dig:diggCount”/><br />
  <strong>Number of comments: </strong><xsl:value-of select=”./digg:commentCount” />
  <p><xsl:value-of select=”./description” /></p><hr />

Обратите внимание на метод обращения к расширенным тэгам Digg. Не забывайте закрывать тэги – таблица должна быть аккуратной. В конце добавьте

 </xsl:template>
 </xsl:stylesheet>

Из RSS в HTML через xsltproc

Настал момент истины! Таблица выглядит прекрасно, но работает ли она? Надеюсь, вы уже установили xsltproc и готовы запустить ее для обработки созданной таблицы и XML-файла Digg. Тогда откройте командную строку и вызовите xsltproc, указав название таблицы стилей, а за ним имя файла, к которому нужно применить таблицу. Если таблица стилей встроена в XML-документ с помощью соответствующей инструкции, название таблицы указывать незачем, xsltproc автоматически определит и использует ее. По умолчанию, результат выводится в stdout (стандартный вывод). Файл для вывода можно указать параметром -o.

Усвоили? Остается набрать следующее:

 xsltproc -o /путь/к/output.htm /путь/к/digg.xsl http://www.digg.com/rss/indexlinux_unix.xml

Если все прошло гладко, дело сделано! Заходите в свою рабочую директорию и открывайте файл output.htm. Вы увидите там чудесно оформленную новостную ленту.

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

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

 <asp:xml DocumentSource=”rss.xml” TransformSource=”digg.xsl”runat=”server” id=”myNews” />

О подходящей альтернативе можно справиться в руководстве по языку.

Скорая помощь

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

Оформите свою RSS-ленту

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

 <?xml-stylesheet href=”rss.xsl” type=”text/xsl” media=”screen”?>

Вот и вся необходимая модификация для данного файла.

Итак, мы сделали это! Взяв исходный XML-файл готовой ленты, мы преобразовали его с помощью таблицы XSLT, чтобы его можно было встроить в сайт. А еще мы воспользовались новообретенными навыками, чтобы присоединить стилевую таблицу к XML-файлу, подготовленному для распространения. Два в одном! Все большее количество браузеров получают поддержку RSS, и недалек тот день, когда необходимость в XSLT полностью отпадет. А пока этого не случилось, минимум усилий может существенно облегчить жизнь пользователям Internet Explorer 6 и Opera.

XSLT не привязан к RSS, его можно применить к любому XML-файлу. Например, Picasa от Google поддерживает экспорт фотоальбома в формате XML. С вашим новым опытом нетрудно преобразовать этот XML в Интернет-фотоальбом! LXF

Выражения XPath

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

Браузеры и RSS

Таблица показывает, как разные браузеры воспроизводят RSS, то есть какие не делают ничего и показывают исходный код XML, какие используют таблицу стилей ленты, а какие подавляют функции таблицы стилей собственным процессором. В настоящее время не существует браузера, который бы пользовался своим процессором лишь при отсутствии таблицы стилей. Если у вас Internet Explorer 7 или Firefox 2, рекомендую дополнительно обзавестись одним из тех браузеров, которые «уважают» таблицы, не подавляя их.

Браузер Бездействие Таблица Подавление
IE 7
X
IE 6
X
pre-IE 6
X
Firefox 2
X
Firefox 1.5
X
pre-Firefox 1.5
X
Opera 9
X
pre-Opera 9
X
Konqueror
X
Персональные инструменты
купить
подписаться
Яндекс.Метрика