- Подписка на печатную версию:
- Подписка на электронную версию:
- Подшивки старых номеров журнала (печатные версии)
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 в приличном виде.
Образцы таблиц
Есть несколько фантастических примеров стилевых таблиц, в которых можно черпать вдохновение. Вот наиболее известные адреса:
- http://newsrss.bbc.co.uk/rss/newsonline_uk_edition/front_page/rss.xml
- http://feeds.feedburner.com/publisherbuzz
Но эти ленты сделаны большими интернет-парнями. Пример, приведенный на иллюстрации, создан игроком поскромнее:
Не надо громадного бюджета: просто освоим таблицы стилей!
Приступим
Наш проект можно разделить на четыре стадии. Мы возьмем 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.
Волшебник 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>
Расставим по местам
Определив раскладку страницы, можно подумать о том, где применить шаблон. Попробуйте набрать следующее:
<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 | | ||
IE 6 | | ||
pre-IE 6 | | ||
Firefox 2 | | ||
Firefox 1.5 | | ||
pre-Firefox 1.5 | | ||
Opera 9 | | ||
pre-Opera 9 | | ||
Konqueror | |