Что я в последнее время распустил занудно-философские сопли. Пора собраться и писать полезные посты. Сказано-сделано. Предыстория.
Направил фид своего блога через FeedBurner чтобы можно было следить за статистикой. Решил потестить, кликнул на ссылку и… смутился. Передо мной предстала самая обычная веб-страница, но Опера предложила добавить фид в свою читалку.
“Как это?” – подумал я и полез в исходный код страницы. Тут меня ждал еще один сюрприз – я увидел обычный XML-код обычного RSS-потока. Потом наконец догадался, что красивая страничка ни что иное, как XML с файлом стилей XSLT!
К чемо это я? Давно мне не нравилась хрень, которую показывает Опера, если кликнуль по ссылке на RSS-канал на автобегиннере. Вот я и решил поправить это дело.
Итак. Имеем сгенеренный XML-файлик с потоком (для примера всего с одним элементом item):
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. | <?xml version="1.0" encoding="windows-1251"?> <rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0"> <channel xmlns:date="http://exslt.org/dates-and-times" xmlns:exsl="http://exslt.org/common"> <language>ru</language> <title>Название фида</title> <link>Ссылка на сайт</link> <description>Описание фида</description> <item> <title>Заголовок записи</title> <link>Ссылка на запись</link> <description>Текст записи</description> <guid>http://www.avtobeginner.ru/news/44/</guid> <enclosure url="урл картинки к записи (если есть)" /> <pubDate>дата</pubDate> </item> ..... </channel> </rss> |
Без заданного форматирования это выводится как набор значений тегов без пробелов и переводом строк.
Задача – поправить эту фигню (сделать из XML валидный HTML-файлик). Добавляем строку (вторая по счету):
1. 2. 3. | <?xml version="1.0" encoding="windows-1251"?> <?xml-stylesheet href="/templates/rss/rss2full.xsl" type="text/xsl" media="screen"?> <rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0"> |
В href конечно же пишем путь, где у вас будет лежать файлик rss2full.xsl.
Теперь рассмотрим сам файлик со стилями (rss2full.xsl). По строкам. Пагнали:
1. 2. | <?xml version="1.0" encoding="windows-1251"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> |
Пояснений не требуется.
1. | <xsl:output method="html" doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN" /> |
Задаем формат вывода и DOCTYPE результирующего документа.
1. | <xsl:variable name="title" select="/rss/channel/title" /> |
В заголовок страницы записываем строку из тега title, расположенного в теге channel расположенного в теге rss.
1. 2. 3. 4. 5. 6. 7. 8. 9. | <xsl:template match="/"> <xsl:element name="html"> <head> <title><xsl:value-of select="$title" /></title> <link href="/templates/style.css" rel="stylesheet" type="text/css" media="all" /> </head> <xsl:apply-templates select="rss/channel" /> </xsl:element> </xsl:template> |
Задаем шаблон для всего потока. Формируем хедер: прописываем title и указываем файл стилей (обычный, CSS) – не забываем писать тот путь, который нужен вам.
В конце вызываем обработку тега channel (строка 7).
1. 2. 3. 4. 5. 6. 7. | <xsl:template match="channel"> <body style="padding: 20px;"> <h1><xsl:value-of select="$title" /></h1> <xsl:apply-templates select="item" /> <p><small>Это RSS-поток с сайта <a href="http://www.avtobeginner.ru/">www.avtobeginner.ru</a></small></p> </body> </xsl:template> |
Собственно шаблон для channel. Во-первых, тег body, куда ж без него. Дальше выводим название потока в h1, вызываем обработчик для тегов item и в коней дописываем что-то наподобие копирайта. Можно написать любую отсебятину.
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. | <xsl:template match="item" xmlns:dc="http://purl.org/dc/elements/1.1/"> <h3> <xsl:choose> <xsl:when test="guid[@isPermaLink='true' or not(@isPermaLink)]"> <a href="{normalize-space(guid)}"><xsl:value-of select="title" /></a> </xsl:when> <xsl:when test="link"> <a href="{normalize-space(link)}"><xsl:value-of select="title" /></a> </xsl:when> <xsl:otherwise> <xsl:value-of select="title" /> </xsl:otherwise> </xsl:choose> </h3> <h4><xsl:value-of select="pubDate" /></h4> <xsl:value-of select="description" disable-output-escaping="yes" /> <xsl:if test="count(child::enclosure)=1"> <p class="mediaenclosure">изображение новости: <a href="{enclosure/@url}"><xsl:value-of select="child::enclosure/@url" /></a></p> </xsl:if> <br /><br /><br /> </xsl:template> |
Шаблон вывода для item‘ов.
Итак, в h3 записываем либо ссылку из тега guid или link, либо просто заголовок элемента. В h4 пихаем дату, вываливаем содержимое тега description.
В конце, если у элемента присутствует тег enclosure – вставляем ссылку на медиа-контент, указанный в нем.
1. | </xsl:stylesheet> |
Усе. Осталось сваять нужный вам CSS и радоваться.


Неплохая, а главное – легко усваемая статья ;)
Только хотелось бы иметь реально работающий .xsl файлик, по типу как у FeedBurner`a.
Выложу вечером.
Картинок в статье нет, по клику на ссылку, пишет, что документ не найден.
Теперь догадываешься зачем нужен валидность, откуда берётся валидный HTML/XHTML, и почему невалидный быдло счётчики – говно?
Зачем валидность нужна XML понятно. Зачем она HTML – нет.
например вот
xsltproc твойщаблон.xsl http://www.likhachev.net/away/ChFHRl4ZHrTR5YHi3ujctIXl2+HpsdrmtbSE5ojksg==/
и вообще html проще обрабатывать когда он валидный
/щ/ш
Куда всё делось то?
автор, починяй примус
Спасибо большое за статью. Помогла несколько структурировать понимание связки RSS + CSS + XML + XSL. Тру вещь)
У меня возникла така проблемка:
1. Формирую файл RSS в формате xml с помощью php.
2. Однако на локальном хосте страница новостей грузится в обычном виде в стандартной верстке обозревателя.
3. Если ТОТ же полученный файл *xml сохранить на диск (ff это позволяет) и открыть через обозреватель, то страница подгружается с заданным моим стилем CSS, который гружу к XML через XSL.
Пробовала через ff и ie. Ситуация одинаковая.
Сайт на серваке на базе денвера (соответственно связки php+апач+mysql). Библиотека XSL в PHP загружена и работает нормально.
файл XML формирую в PHP стандартно:
Буду очень благодарна за любую помощь. Может парсеру нужно каким-то образом указывать на работу с XSL. От чего может зависеть ещё отработка XSL из XML?
Модули PHP тут совершенно ни причем. XML+XSLT обрабатывает браузер.
Во-первых, проверьте пути к файлам (xslt, css).
Во-вторых, заголовки, который отдает денвер.
Спасибо за подсказки…
1) пути к файлам пробовала задавать по-разному: и относительно и с аштитипи и размещать файлы стилей пробовала как можно более гуманно (и в корневом и путь с “точками и слешами” – всё по очереди) – не помогло.
2) сам денвер вроде отрабатывает. Я в PHP объявляю с помощью хэдера, что передаю файл формата XML и в связи с этим сама лента отображается нормально браузером. НО в стандартном виде. Если просматривать код страницы в xml (из ff) то сам файл xml формируется верный, в заголовке указан файл для преобразования XSL.
Подозревала, что у меня не работает xsl библиотека в PHP, но пробовала переустанавливать, прописывала в самом денвере, чтобы работал с xsl.
Из других вариантов также пробовала:
3) добавлять в файл htaccess строки
AddType application/x-httpd-php .xml .xsl
php_value short_open_tag Off
4) в файле денвера по работе с апачем пробовала прописывать (apache.pl)
# Start apache.
system(“start $exe -w –with-xsl”);
5) сам PHP работает нормально. – все библиотеки находит (проверяла через php-cgi).
6) ..в конце концов в файле пхп.ини нет лишних инклудов и т.п.
7) танцевала с бубном…
Наткнулась, что у кого-то была проблема подобного рода но тот работает с аспом. Решил проблему, позволив формируемому объекту XML делать свои запросы серверу, дописав: objXML.setProperty “ServerHTTPRequest”, true
Не подскажите, какие проверки можно ещё сделать, чтобы сузить круг поиска?
Подозреваю, что это либо вообще невозможно, так как реализации ни у кого не встречала, либо я недопонимаю самых простых вещей.
Как сделать так, чтобы люди, подписавшиеся на мою ленту, видели её красивой?
Способ с XML + XSL – это лишь один из нескольких, которые я пробовала. Может есть решение другое? не обязательно простое.
Спасибо за понимание :)
Какие у вас странные сложности
всё что нужно, так это “правильный” http заголовок
wget –no-proxy –save-header -O /dev/stdout breys.ru/rss/ |head
Content-Type: application/xml; charset=utf-8
и xml файл составленный в формате rss
для работы с xslt удобно, пока не запомните, пользоваться xslt процессором
даёшь ему на вход 2 файл xsl и xml на выходе получаем, то что запрограммировано в xslt
например вот так xsltproc breys.ru/www/template/index2.xsl breys.ru/www/tmp/blog.xml
вроде ещё для FF3 есть плагины
и не надо ничего усложнять, xslt классная штука, а опытных руках отличная – глядим на яндекс
зы: все бровзеры одинаково обрабатывают rss, так что ориентируйтесь лучше на роботы типа фрибурнера, тоесть вы кормите ему свой rss а остальное его проблемы
Окей! Огромнейшее спасибо за ответ.
Действительно, всё гениальное – просто.