RSS feed: The CityDesk Connection

published: Sat, 5-Mar-2005   |   updated: Thu, 27-Oct-2005

An old acquaintance, Jeroen Pluimers, was kind enough to gently point out that my RSS feed was totally, er, sporked.

Hah, I thought, you're talking doggy doo-doos, Jeroen, but on checking I saw that he was completely correct. My RSS feed suddenly just contained relative URLs and not absolute ones. Gaak.

A bit of background. At the moment I don't publish a dynamic web site in the sense of using something like PHPNuke or DotNetNuke. My web site just comprises static pages. However I do use a content management system called CityDesk to manage it all, so it does have some dynamic properties.

Essentially, CityDesk provides a "poor man's" CMS. You write all your content off-line and then you publish it to your web site. When you publish your articles, CityDesk applies the templates you've provided (you also write these) to the text, and uploads the fully formed HTML to your website. Since the template contains all the paraphernalia like links to the CSS file, the unchanging headers, the columns, etc, etc, all you tend to write is simple text for each article.

Obviously, CityDesk ignores unchanged content on publishing your web site (otherwise you'd be publishing your entire site for every minor change on an article) and it does some snazzy text substitution, and the like. All the content is kept in a single database file so it's easy to keep backups. All in all, a very nice CMS for small web sites.

Anyway, I'd set up an RSS template in CityDesk to produce my RSS feed (which as you know is just an XML document). Here's the template I was using:

<?xml version="1.0" encoding="utf-8"?>
{$ setDateTimeFormat "English" "ddd, dd MMM yyyy" "HH:mm:ss 'MST'" $}
<rss version="2.0">
    <channel>
        <title>boyet.com  :  algorithms for the masses  :  by julian m bucknall</title>
        <link>http://www.boyet.com</link>
        <description>A site that blah, blah</description>
        <language>en-US</language>
        <pubDate>{$ publishDate $} {$ publishTime $}</pubDate>
        <lastBuildDate>{$ publishDate $} {$ publishTime $}</lastBuildDate>
        <copyright>Copyright 2003-2005 Julian M Bucknall.</copyright>
        <managingEditor>julianb.at.boyet.com</managingEditor>
        <webMaster>julianb.at.boyet.com</webMaster>
        <image>
            <title>boyet.com  :  algorithms for the masses  :  by julian m bucknall</title>
            <url>http://www.boyet.com/images/rssbridge.gif</url>
            <link>http://www.boyet.com</link>
            <width>140</width>
            <height>50</height>
            <description>A site that blah, blah</description>
        </image>

{$ foreach 8 a in (folder "Articles") sortDescendBy .filedDate $}

<item>
	<title>{$ a.headline $}</title>
	<link>{$ a.link $}</link>
	<description> 
		{$ a.teaser $}
	</description>
	<pubDate>{$ a.modifiedDate $} {$ a.modifiedTime $}</pubDate>
</item>

{$ next $}

</channel>
</rss>

The special CityDesk markup is contained within {$ and $} pairs, and if you look carefully it has loop constructs as well. The loop is essentially extracting some info from each of the last eight articles to form an <item> element in the final RSS document.

The problem was that a.link (i.e., the hyperlink for the current article a) was being compiled to a relative URL and not an absolute URL. For the rest of the web site that's just fine; it's what you want. For the RSS feed it was totally the wrong thing to do: an RSS feed doesn't exist within the context of your web site, it gets pulled all over the web. The links in the RSS feed must be absolute.

Well, CityDesk has a command that forces links to be absolute:

{$ withAbsoluteLinks "http://www.boyet.com/" $}

The help is a little obtuse at this point. It states that the command only works for the current document, but I found that if you put it in a template (any template) it applies across the entire web site. Urk. Even worse, if you put it in an article (like my RSS feed document) it forces absolute URLs everywhere as well: it seems that this flag is global somehow. I'm reporting it to those awfully nice people at FogCreek.

I thought I'd solved this issue on Thursday evening, but then something happened that is the bane of developers everywhere. I made a last minute change that I was convinced would solve the problem and published it without testing. (Actually what happened was I made the change, got a call from my wife of some urgency, and then published the site the next day, thinking I'd done due diligence to check it worked.)

Bam, my RSS feed got published with relative links. Major slap on wrist: always test, never assume.

Anyway, for those who use CityDesk, here's my final solution to producing an RSS 2.0 feed with CityDesk that shows the last eight articles in reverse order (most recent first). Note that the times in the compiled output are quoted as Mountain Standard Time (MST), modify according to your preferences. (Note that my solution doesn't take into account the issue with the absolute flag: currently I've published my site with absolute links.)

The RSS template (make sure that you set the template's extension property to ".xml" or ".rss"):

<?xml version="1.0" encoding="utf-8"?>
{$ setDateTimeFormat "English" "ddd, dd MMM yyyy" "HH:mm:ss 'MST'" $}
<rss version="2.0">
    <channel>
        <title>boyet.com  :  algorithms for the masses  :  by julian m bucknall</title>
        <link>http://www.boyet.com</link>
        <description>A site that blah, blah</description>
        <language>en-US</language>
        <pubDate>{$ publishDate $} {$ publishTime $}</pubDate>
        <lastBuildDate>{$ publishDate $} {$ publishTime $}</lastBuildDate>
        <copyright>Copyright 2003-2005 Julian M Bucknall.</copyright>
        <managingEditor>julianb.at.boyet.com</managingEditor>
        <webMaster>julianb.at.boyet.com</webMaster>
        <image>
            <title>boyet.com  :  algorithms for the masses  :  by julian m bucknall</title>
            <url>http://www.boyet.com/images/rssbridge.gif</url>
            <link>http://www.boyet.com</link>
            <width>140</width>
            <height>50</height>
            <description>A site that blah, blah</description>
        </image>

{$ .body $}

</channel>
</rss>

The article named "RSS" that links to the RSS template:

{$ withAbsoluteLinks "http://www.boyet.com/" $}
{$ foreach 8 a in (folder "Articles") sortDescendBy .filedDate $}

<item>
	<title>{$ a.headline $}</title>
	<link>{$ a.link $}</link>
	<description> 
		{$ a.teaser $}
	</description>
	<pubDate>{$ a.modifiedDate $} {$ a.modifiedTime $}</pubDate>
</item>

{$ next $}

(For those who have ever tried publishing CityDesk code in an article in a CityDesk site: replace all < with &lt; and replace all {$ with {{$$}$ and $} with ${$$}}. Got that? Good <g>.

Update

I still reckon it's a bug, but there is a workaround. Mark every template with {$ withAbsoluteLinks "" $} except the template that is producing the RSS feed. For this one mark it with {$ withAbsoluteLinks "http://www.YourFaveUrl" $}.

The weird thing about this solution was that the problem had been discussed to death in the old CityDesk forum on the FogCreek site back in 2003. However, those pages are not scanned by Google, therefore I couldn't find the workaround. There is a way to get to the old forums and there is a search button for them, but I didn't see this and so missed finding the solution out on my own. Oh well, at least now the workaround can be Googled on my own website. (Thanks to tk for pointing the way.)