Undefined » Articles » Skinning RSS feeds with XSL(T)
What is XSLT
XSLT stands for Extensible Stylesheet Language Transformations and is the means by which you can "transform" any XML file into something that looks better than the default node tree.
If you have looked at my news feed, http://www.chris-holden.com/rss/news.xml you will be able to see what I mean. The RSS feed for this site has been skinned with the look and feel of the rest of the website. You may need view the page in a modern browser, e.g. Firefox, Netscape 8, Internet Explorer 6 etc.
How is it done?
The first thing you need to do is output your RSS feed with the following line
<?xml-stylesheet type="text/xsl" href="stylesheet.xsl"?>
This line should immediately follow the <?xml ...?> line which should be on the first line of your file. That is all the modification you need to make to the RSS feed.
The XSL File
The next thing you need to do is create an XML file called stylesheet.xsl and save it in the same directory as your news feed. You can view my XSL file here for reference.
The bare minimum code that needs to be in this file is:
<?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet version="1.1" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="html" /> </xsl:stylesheet>
But that doesnt actually do anything. The XSL file is XML, so you have to be perfect in your HTML and templates.
After the xsl:output tag you include your HTML that should be displayed in place of the node tree. For the moment, lets say you have this HTML:
<html> <head> <title>News Feed</title> </head> <body> <p>This is my first XSL attempt!</p> </body> </html>
Then all your news feed will display is a line saying This is my first XSL attempt!
. To actually get content from your news feed into the HTML you need to use XSL templates.
What is an XSL Template?
XSL templates are used to match specific tags from the XML file you are trying to transform. The template has a match attribute which allows you to single out individual XML tags, in a directory like way. For example:
<xsl:template match="/">
<html>
<head>
<title>News Feed</title>
<link rel="stylesheet" href="../css/rss.css" type="text/css" />
</head>
<body>
<p>This was produced by a template</p>
</body>
</html>
</xsl:template>
The above template matches the element "/" which is the root node, that is, <rss>. The root template is automatically applied to the document, however, other templates will not be, they need to be applied through the following tag:
<xsl:apply-templates select="rss/channel" />
This will apply the template that has a match="channel" attribute and the HTML and other templates inside the template will be output. Nesting templates can be quite useful for repeating HTML on item tags to produce lists, for example:
<h3>Latest Content</h3>
<p>Below is the latest content available from this feed:</p>
<ol>
<xsl:apply-templates select="item" />
</ol>
<xsl:template match="item">
<li class="item">
<p class="link">
<a href="{link}" title="{title}"><xsl:value-of select="title" /></a> (<strong><xsl:value-of select="category" /></strong>)
</p>
<p class="text">
<xsl:value-of select="description" />
</p>
</li>
</xsl:template>
The template will print out a list item for each of the items it finds in the news feed.
Other Tips
You may notice in the last template code for items, that there are few other tricks employed, namely the <xsl:value-of /> tag. This tag does what it says on the tin. It selects the value of the named attribute. So to get the value of the description you would use
<xsl:value-of select="description" />
And that will print the value of the description tag inside the current item tag. You can also see that I included a clickable link to the item. Because the link and title of the item need to be quoted values in the HTML, you can not use the <xsl:value-of /> tag. Instead, you can use the following trick:
<a href="{link}" title="{title}"><xsl:value-of select="title" /></a>
The important parsts a the href of the link becomes {link} and the title tag becomes {title}. I could have alternately put the item description as the title of the link with the following code, not that the link text (which is not quoted) is still displayed with value-of.
<a href="{link}" title="{description}"><xsl:value-of select="title" /></a>
Declaring Values
If you are going to need global values in the XSL file, you can declare them like this, for example the feed title.
<xsl:variable name="title" select="/rss/channel/title"/>
Now the variable title can be used anywhere in your templates by using the following
<xsl:value-of select="$title" />
Note that declared variables are preceded by a dollar sign so as not to be confused with selecting the value of a node
XSL Functions
XSL comes with some built in functions, while it is not a proper programming language and the syntax probably abhors most, they can be quite useful. For instance, one of the drawbacks of news feeds is having to have the date in RFC format. I came up with this small set of statements that are inside the item template to format the date to something more readable.
<xsl:variable name="day" select="substring-before(pubDate, ',')" /> <xsl:variable name="date" select="substring-before(substring-after(pubDate, ' '), ' ')" /> <xsl:variable name="month" select="substring-before(substring-after(substring-after(pubDate, ' '), ' '), ' ')" /> <xsl:variable name="year" select="substring-before(substring-after(substring-after(substring-after(pubDate, ' '), ' '), ' '), ' ')" /> <xsl:value-of select="concat($day, ', ', $date, ' ', $month, ' ', $year)" />
The above snippet of code formats the RFC date as Thu, 16 Feb 2006
posted by Chris
16 February 2006