Using XSLT And XML Transformations To Style My Blog's RSS Feed As An HTML Page
For years, I've been using CSS to add a touch of style to my blog's RSS feed. For those of you who are relatively new to web development, RSS stands for "Really Simple Syndication"; and was one of the primary ways that content was distributed on the web prior to the "Social Media" era. RSS, at its core, is just an XML document. And, as I just learned from an article on RSS by Jon Christopher, the XML in an RSS feed can be transformed using XSLT. To be honest, it's been about 11-years since I looked at XSLT; so, I thought it would be fun to try and apply some XML Transformations to my RSS feed.
I first learned about XSLT (Extensible Stylesheet Language Transformation) back in 2007, when I gave an introductory talk about XML and XSLT at Nylon Technology. Since then, I've only revisited XSLT a handful of times. It was always interesting to me as a concept; but, also felt far more complicated than anything I ever had to do on a daily basis.
An XSLT document is, itself, an XML document that is used to transform an input XML document into output XML document. Which - as I've learned recently - means that we can use XSLT to transform an RSS (XML) feed into XHTML document. XHTML is just an HTML specification that adheres to XML formatting rules. Which means, we can use XSLT to transform an RSS feed into a "normal web page".
According to Jon Christopher, to get this to work, all we have to do is add the following line to the top of our RSS feeds:
<?xml-stylesheet type="text/xsl" href="...." media="screen" ?>
... where the href
attribute points to our XSLT file.
With this in place, browsers that support XSLT will automatically pull the XSLT document down and transform the RSS feed's XML directly in the browser! Wicked!
To play around with this, I created the following XSLT document for my RSS feed. It consists primarily of the following XSLT constructs:
<xsl:value-of select="...." />
- Used to output the value of an XML node.attribute={ .... }
- Used to embed a value within an XML attribute.<xsl:for-each select="....">
- Used to loop over a collection of selected XML nodes.
The rest of the XSLT document is basically just XHTML:
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!-- This causes the HTML doctype (<!doctype hmlt>) to be rendered. -->
<xsl:output method="html" doctype-system="about:legacy-compat" indent="yes" />
<!-- Start matching at the Channel node within the XML RSS feed. -->
<xsl:template match="/rss/channel">
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>
<xsl:value-of select="title" />
</title>
<link rel="shortcut icon" type="image/ico" href="{ link }favicon.png" />
<link rel="stylesheet" type="text/css" href="//fonts.googleapis.com/css?family=Merriweather:300,400,700,900|Open+Sans:300,400,600,700,400italic,300italic" />
<link rel="stylesheet" type="text/css" href="{ link }linked/css/rss-xsl.css" />
</head>
<body>
<div class="hero">
<a href="{ link }people/who-rock-my-world.htm" class="hero__link">
<img
src="{ link }people/random-image"
alt="Ben Nadel rocking out with some super fabulous people!"
class="hero__image"
/>
</a>
</div>
<h1 class="title">
<xsl:value-of select="title" />
</h1>
<p class="description">
<xsl:value-of select="description" />
</p>
<ul class="posts">
<xsl:for-each select="./item">
<li class="posts__post post">
<h2 class="post__title">
<a href="{ link }" class="post__link">
<xsl:value-of select="title" />
</a>
</h2>
<p class="post__preview">
<xsl:value-of select="description" />
<a href="{ link }" class="post__more">Read more</a>
</p>
</li>
</xsl:for-each>
</ul>
<p class="cta">
<a href="{ link }" class="cta__link">View all posts on <strong>BenNadel.com</strong></a>
</p>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
And, if I add this XSL document to the top of my RSS feed (truncated below):
<?xml version="1.0" ?>
<!-- MY XSLT document to transform the RSS feed into an XHTML page. -->
<?xml-stylesheet type="text/xsl" href="https://www.bennadel.com/linked/xslt/rss.xsl" media="screen" ?>
<rss version="2.0">
<channel>
<title>Ben Nadel's Web Development and User Experience Feed @ BenNadel.com</title>
<link>https://www.bennadel.com/</link>
<!-- ... Truncated for blog post ... -->
</channel>
</rss>
... I get the following output:
How cool is that!
Honestly, I have no idea if this is useful. I don't even know if anyone still uses RSS feeds to subscribe to my blog. But, it was a fun little learning adventure. And, a nice little refresher in XSTL and XML.
Want to use code from this post? Check out the license.
Reader Comments
I still use RSS to subscribe :)
There are lots of other cool things you can do with RSS. I've written about some it here: https://steele.blue/rss-club/
@Matt,
Good read :)
... ha ha, true. I have so little patience for Social Media. I can look at Facebook for about 3-mins before I get frustrated and feel like I should be doing something else.
I have been, and will always be a big fan of RSS feeds. It will be a sad day if the stalwart bloggers (like you) abandon RSS so I'm thrilled to see the attention. I haven't messed with XSLT in many years but this brings back many good memories. A real pain to debug but a lot of fun!
@Mike,
I appreciate that, good sir. Once you have one working, it doesn't really require any "upkeep" to keep it going. And, every now-and-then, I can tweak it a bit, like in this post.
I was actually just thinking about RSS today; and, how I really should be more proactive about following other people like I used to back in the day. Life just got so busy, and I fell off the wagon, and am usually heads-down in my own little work-silo.
I gotta get outside my comfort zone more.
Well, that comment went super tangential super quick :P
There is a typo in the production XSLT at line 20 (where you link to the Google Fonts API), which renders the XSLT invalid: the ampersand needs to be entity escaped.
@DotJohn,
Oh man, good catch! That was something I actually just added yesterday! It didn't occur to me to test the RSS feed. Shame shame. Fixing now.
@DotJohn,
Consider it fixed! Again, thank you so much catching that #TeamWork