XML feeds have become a common way for people to keep updated on their favorite websites, no matter what specification they follow (RSS, Atom, etc.). XML files suffer though from poor usability by nature as they are not friendly to look at in the browser. Your feed handler (e.g. FeedDemon, FeedReader, NewsGator, etc.) will, of course, display them in a nicely formatted way, but in this article we’ll see two ways to spice up their boring browser display:

  1. Using CSS definitions on the individual notes
  2. Applying an XSL Tranformation file

For our example, we’ll assume that we are serving feeds in RSS 2.0 format, but the principles discussed should apply for any type of XML feed. You can rest assured that this type of formatting will not change the way your readers use your feeds. I first got this idea after reading a blog entry by Pete Freitag.

First, the original XML feed

So, Let’s a take a look at a typical RSS 2.0 feed: an example of a possible “latest articles” feed for this site:

<?xml version="1.0" encoding="ISO-8859-1" ?>
<rss version="2.0">
<channel>
	<title>xefteri.com</title>
	<link>http://www.xefteri.com</link>
	<description>The latest articles from xefteri.com</description>
	<language>en-us</language>
	<copyright>Copyright 2005 xefteri.com</copyright>
	<docs>http://blogs.law.harvard.edu/tech/rss/</docs>
	<lastBuildDate>Mon, 17 Mar 2003 00:00:00 MST</lastBuildDate>

	<item>
		<title>Improving an XML feed display through CSS and XSLT</title>
		<description>XML feeds, though useful, are boring to look at in a browser because they are simple XML files. It's possible though to make them easier on the eye, and in this article we'll look at two ways of doing that. First, we'll use simple CSS properties to format each XML node, and then we'll use a little more complex but much more powerful XSL transformation.</description>
		<pubDate>Sun, 06 Mar 2005 00:00:00 MST</pubDate>
		<link>http://www.xefteri.com/articles/show.cfm?id=24</link>
	</item>

	<item>
		<title>Identity fields in Oracle and SQL Server</title>
		<description>While it may be relatively easy to create an incrementing and unique identifier inside a table in SQL Server, things get tricky with Oracle. In this article, we'll see the differences between the two databases and offer a way of solving the problem.</description>
		<author>email@yoursite.com (Evagoras Charalambous)</author>
		<pubDate>Mon, 17 Mar 2003 00:00:00 MST</pubDate>
		<link>http://www.xefteri.com/articles/show.cfm?id=23</link>
	</item>

	<item>
		<title>Exporting Word files to HTML</title>
		<description>In this article we will first discuss the case for and against using Word as your HTML editor. Then we will see how to properly save a Word file to smaller, more compact HTML files. Third and last, we will see how to do this through code, and possibly create a batch process for converting numerous Word files to HTML at once.</description>
		<author>email@yoursite.com (Evagoras Charalambous)</author>
		<pubDate>Wed, 05 Mar 2003 00:00:00 MST</pubDate>
		<link>http://www.xefteri.com/articles/show.cfm?id=22</link>
	</item>

</channel>
</rss>

We are not doing anything new here. We are following the RSS 2.0 specification to create this feed: a channel wrapper with its feed properties, including as many item nodes as we want of the latest posts (with their own properties). Here’s what this feed looks like through the browser:

Basic yes, friendly to look at no. So, let’s see how to improve this display.

Formatting through CSS

The principle here is that since a feed is made up of XML nodes, we can apply CSS formatting on them to change the way they display in the browser. First we need to add the CSS reference inside the XML file. This can be a full URL with the domain, or simply a website relative address:

<?xml version="1.0" encoding="ISO-8859-1" ?>
<?xml-stylesheet type="text/css" href="/includes/css/rssfeed.css" ?>
<rss version="2.0">

Under channel, we have the mandatory title, which is the feed title. To edit the display of this node to a bigger text size we can simply add this to our CSS:

channel title {
 font-size:140%;
}

We can follow this principle to format the rest of the notes. One issue that we have to keep in mind is that if there is more than one node named title, then they will all inherit the same properties. In the example shown, the second tag will also display with font size 140%. To fix this, we will need to create a separate CSS property for it and change the size:

channel item title {
 font-size:100%;
}

Our feeds most often contain properties that we may not necessarily want to have them display in our improved version. So. we can group all nodes that we want to hide and change their display property to hidden. The order of the nodes in the XML file will be maintained, unless you can figure out a way to change this through CSS.

Here is a complete CSS file as an example:

channel link, channel language, channel copyright, channel managingEditor, channel webMaster, channel docs, channel lastBuildDate {
	display:none;
}
rss {
	font-family:Verdana, Arial, Helvetica, sans-serif;
	font-size:0.7em;
	line-height:130%;
	margin:1em;
}
<em>/* HEADER */</em>
<em>/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/</em>
channel title {
	display:block;
	padding:0.4em 0.2em;
	color:#FFF;
	border-bottom:1px solid black;
	font-weight:bold;
	font-size:140%;
	background-color:#4483C7;
}
channel description {
	display:block;
	float:left;
	font-size:130%;
	font-weight:bold;
	margin:0.5em;
}
<em>/* CONTENT */</em>
<em>/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/</em>
channel item {
	background-color:#FFFFEE;
	border:1px solid #538620;
	clear:both;
	display:block;
	padding:0 0 0.5em;
	margin:1em;
}
channel item title {
	background-color:#538620;
	border-bottom-width:0;
	color:#FFF;
	display:block;
	font-size:110%;
	font-weight:bold;
	margin:0;
	padding:0.3em 0.5em;
}
channel item description {
	display: block;
	float:none;
	margin:0;
	text-align: left;
	padding:0.2em 0.5em 0.4em;
	color: black;
	font-size:100%;
	font-weight:normal;
}
channel item link {
	color:#666;
	display:block;
	font-size:86%;
	padding:0 0.5em;
}
channel item pubDate {
	color:#666;
	display:block;
	font-size:86%;
	padding:0 0.5em;
}

Here’s a screenshot of the resulting output:

XSL Transformation

Applying an XSL stylesheet to the XML feed has the advantage of being able to fully customize the display, like being able to add links or change the order of the nodes. The transformation needs to happen on the client so that the XML remains intact.

First we add the reference to the XSL file inside the feed:

<?xml version="1.0" encoding="ISO-8859-1" ?>
<?xml-stylesheet type="text/xsl" href="latest.xsl" ?>
<?xml-stylesheet type="text/css" href="latest.css" ?>
<rss version="2.0">

We can add the XSLT specification, as well as leave the CSS link there as well. Having both added is perfectly fine, as only one of them is going to be used in the end. If the browser understands XSL, then it will use that and ignore the CSS. I am not going to explain here how to create an XSL transformation file, you can find tutorials on that elsewhere. Instead, let’s see the complete XSL file:

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/rss">
	<html>
	<head>
		<link href="xsl.css" rel="stylesheet" type="text/css" />
		<style type="text/css">
			body {
				font-size:0.83em;
			}
		</style>
	</head>
	<body>
		<div id="logo">
			<xsl:element name="a">
				<xsl:attribute name="href">
					<xsl:value-of select="channel/link" />
				</xsl:attribute>
				<xsl:value-of select="channel/title" />
			</xsl:element>
		</div>
		<div class="Snippet" style="border-width:0; background-color:#FFF; margin:1em">
			<div class="titleWithLine">
				<xsl:value-of select="channel/description" />
			</div>
			<dl style="padding-right:1em">
				<xsl:for-each select="channel/item">
					<dd>
						<xsl:element name="a">
							<xsl:attribute name="href">
								<xsl:value-of select="link"/>
							</xsl:attribute>
							<xsl:value-of select="title"/>
						</xsl:element>
					</dd>
					<dt>
						<xsl:value-of select="description" /><br />
						<span class="comments"><xsl:value-of select="pubDate" /></span>
					</dt>
				</xsl:for-each>
			</dl>
		</div>
		<div id="footer">
			<xsl:value-of select="channel/copyright" />
		</div>
	</body>
	</html>
</xsl:template>
</xsl:stylesheet>

The important thing to notice here is that you can output complete HTML, together with links to external CSS files, for even improved customization of the display. If you already have a stylesheet that you use on your site you can make a reference to it, and use it in the XSL file to create a similar look and feel. This is what is shown above, with the link to the CSS file “xsl.css“. There are also many ways to define an XSLT file, like using templates, mine is simply one of them and not necessarily the best one. It’s simple enough though that it does the job I want. Use the code as it is or modify it to suit your situation. Here’s a screenshot of the resulting browser output:

The display now looks a lot better, and the titles are actually active links to the articles.

In this article I have shown two techniques to improve upon the browser display of your XML feeds, no matter what specification they follow. One involves the use of CSS and the other a complete XSL transformation. The CSS method is easy to implement, while the XSLT offers great customization. I am sure that by applying these techniques, your users will be pleasantly surprised when they get to your XML feeds.

7 Responses to Improving an XML feed display through CSS and XSLT

  • Luke

    This is the kind of simple approach that I really appreciate. Thanks for your work.

  • Katie

    great examples, thank you!

  • LINTU

    Hi.. It’s workiong perfectly in google chrome. BUt does’nt work in mozilla. Please give a solution

    • Evagoras Charalambous

      Please provide specific examples of what you tried and how it doesn’t work in Mozilla.

  • wayne

    This is a great article and greatly appreciate the simplicity of it. I get the RSS/XML and the XSL and XSLT but not sure how you insert the stylesheet into the RSS/XML feed when it comes from another site where you don’t own the actual feed. For example, let’s say I have an RSS feed from Yahoo (http://dir.yahoo.com/rss/dir/getrss.php?biz), and what to format it differently on my website, similiar to your above example. How would I do this when I don’t curate/owner the actual RSS/XML file?

    Your help is greatly appreciated.

    Wayne

    • Evagoras Charalambous

      One way you could accomplish what you want is to fetch the XML data through a server side call and then parse out the contents and display them in any shape you want. You would then move from the client handling all the processing to the server.

      I am not sure how you could accomplish this without any sort of server manipulation. One possible scenario (have not tested this) is to perhaps fetch the contents of the XML through an AJAX call, then inject your XSL reference into the document contents and try to evaluate the result onto your page. It might be doable, and if you go that route, I would be curious to hear the outcome!

  • Kyle Magee

    This tutorial is gang busters. I’m not sure why this isn’t built into the RSS on the big CMS platforms that offer this method of syndication. Browsers like FF and IE seem to have taken it upon themselves to cover this gap but many non-tech users of chrome end up scratching their heads thinking that the browser is broken or something. this is a great article.

Leave a Reply

Your email address will not be published. Required fields are marked *