Сортировка RSS-ленты по дате с использованием XSLT

(Development) · English (28,043 views)

В моей предыдущей заметке я описал, как отобразить RSS-ленту в браузере с использованием XSLT. Но иногда важно не просто вывести, но еще и изменить порядок записей в ленте, например, отсортировать их по дате. XSLT 1.1 позволяет сортировать по сложным типам данных, но, к сожалению, XSLT 1.0 не позволяет, потому необходимо извлечь отдельные части даты.

Для начала я покажу, насколько просто отсортировать по дате в XSLT 1.1. Необходимо объявить пространство имен dc:

1
2
3
4
<xsl:stylesheet version="1.1"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:digg="http://digg.com//docs/diggrss/"
 xmlns:dc="http://purl.org/dc/elements/1.1/">

Теперь осталось только отсортировать:

1
2
3
<xsl:apply-templates select="item">
  <xsl:sort select="pubDate" data-type="dc:date" order="ascending"/>
</xsl:apply-templates>

Как я сказал ранее, в XSLT 1.0 необходимо разрезать дату, получив день, месяц, год и т.д. Для преобразования месяца в число я буду использовать следующее XML-дерево:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
  <months:months>
    <name>Jan</name>
    <name>Feb</name>
    <name>Mar</name>
    <name>Apr</name>
    <name>May</name>
    <name>Jun</name>
    <name>Jul</name>
    <name>Aug</name>
    <name>Sep</name>
    <name>Oct</name>
    <name>Nov</name>
    <name>Dec</name>
  </months:months>

Настало время написания кода для сортировки:

1
2
3
4
5
6
7
8
9
10
11
<xsl:variable name="vMonths" select="document('')/*/months:*"/>
<xsl:apply-templates select="item">
  <xsl:sort select="substring(substring-after(substring-after(substring-after(pubDate, ' '), ' '), ' '), 1, 4)" order="ascending"/>
  <xsl:sort select="count($vMonths/name[
                 .=substring(substring-after(substring-after(current()/pubDate, ' '), ' '), 1, 3)]
                 /preceding-sibling::name)"

           data-type="number"
           order="ascending"/>
  <xsl:sort select="substring(substring-after(pubDate, ' '), 1, 2)" data-type="number" order="ascending"/>
  <xsl:sort select="substring(substring-after(substring-after(substring-after(substring-after(pubDate, ' '), ' '), ' '), ' '), 1, 8)" data-type="text" order="ascending"/>
</xsl:apply-templates>

Вот и все. Элементы ленты будут отсортированы по дате в порядке возрастания.

Вы можете посмотреть результаты здесь или скачать исходные коды здесь.

Рекомендуемые книги

11 Responses to this entry

Subscribe to comments with RSS

test
said on 23.09.2006 at 17.42 · Permalink

интересно, а можно убрать записи с повторяющейся датой?

said on 25.09.2006 at 13.44 · Permalink

Может это лучше делать на сервере?

adamr @
said on 09.10.2006 at 15.36 · Permalink

Hi, I am slowly developing a website and I wanted to put some RSS feeds into my site to pad out the content. They will update as well which means I don’t have to worry about that.

I was thinking of using XSLT and your article is very interesting. I have two questions:
1. Can I just inlclude the XML file as a PHP include and the page will display the transformed XML as HTML with the rest of the page around it?
2. How can you limit the number of items you bring through. i.e. If you only want the latest story from each feed.

Thanks for any help/advice in advance!

said on 10.10.2006 at 5.01 · Permalink

Hello, adamr
Thank you for you interest. Of course, you can do all you need using XSLT, but I think this is not so good solution. It will be better to parse XML using native PHP libraries and build result HTML.

1. You can’t do this, but… you have ability to transform XML using XSLT with PHP code, just look at XSLT extension or DOM XML extension. There are many articles in the net about this (just look at Google

2. To show only lastest of strories you can use something like (XSLT 1.1)

1
2
3
4
5
6
<xsl:for-each select="item">
  <xsl:sort select="pubDate" data-type="dc:date" order="ascending"/>
  <xsl:if test="position() = 1">
    <xsl:apply-templates/>
  </xsl:if>
</xsl:for-each>

instead of

1
2
3
<xsl:apply-templates select="item">
  <xsl:sort select="pubDate" data-type="dc:date" order="ascending"/>
</xsl:apply-templates>
adamr @
said on 10.10.2006 at 11.08 · Permalink

Hi Kpumuk, thanks for your reply. I have spent a long time searching through Google and I agree that PHP seems to be the easiest way to transform XML into HTML for use in a page. I am already using one called CaRP which works quite well.

In principle though XSLT should be a good way of doing this but perhaps at a higher level than I am trying…..;-)

said on 25.11.2006 at 14.14 · Permalink

Thanks! This is just what I needed, you saved me a lot of time!

said on 09.06.2007 at 21.49 · Permalink

А как отсортировать rss средствами xml? Загонять все в массив?

said on 09.06.2007 at 22.51 · Permalink

Ошибка, не средствами xml, а php.

said on 16.03.2008 at 20.16 · Permalink

Интересно, а какой у вас плагин подсветки синтаксиса?

Comments are closed

Comments for this entry are closed for a while. If you have anything to say – use a contact form. Thank you for your patience.