Textpattern tips, tutorials and code snippets

Create an RSS Feed for Future-Dated Content

One of the things Textpattern handles relatively well is time-sensitive content. Its ability to render past- and future-dated material, as well as setting expiration dates, is key to building more complicated functionality like event calendars. (In fact, the plugin smd_calendar is completely dependent on this functionality.) But because the <txp:feed_link /> tag relies on the posted date to timestamp items, and you cannot have future-dated material inside RSS, TXP provides no native means to generate a feed based on a calendar of upcoming events. In building DeCal, a site completely reliant on events occurring in the future, I had to create a custom RSS feed in order to show events as they were added to the calendar. As it turns out, it was not too difficult.

This tutorial covers building a custom RSS 2.0 feed for future-dated articles, which is not possible “out of the box”. We’ll explore RSS syntax, create a new section and page template for the feed, and then use basic <txp:article_custom /> tags to render nicely formatted content.

The RSS 2.0 Framework

I chose RSS 2.0 because of its near-ubiquitous adoption and thorough documentation. For those unfamiliar with RSS’s XML structure, it is essentially broken into two parts: the metadata about the feed, and then the individual items after that. Not unlike the structure of a typical HTML document. Here is the wrapping markup:

<?xml version="1.0"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
   <channel>
      ... metadata about feed ...
      ... individual items ...
   </channel>
</rss>

We’ll cover both the metadata and the individual items.

Setting Up Textpattern

This is the easy part. In order:

  1. Determine what sections or categories of articles will appear in the feed. For me, this was just one: all of my calendar entries are posted into the section “event”, so that is what I will used in the examples below.
  2. Create a new section called feed. No articles will actually get posted to this new section, but it will serve as the templating area for the XML. Ultimately, your RSS feed will resolve at www.yoursite.com/feed. (Assuming you are using clean URLs.)
  3. Create a new page called feed_template. Assign this page to the feed section you created in step 2.
  4. Create a new article-type form called feed_item and leave it blank for now. You’re ready to get started!

Once everything is set up, copy the following into the feed_template page:

<?xml version="1.0"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
   <channel>
      <title>Name of Your Feed</title>
      <link><txp:site_url /></link>
      <description>Plain text description of the feed's content.</description>
      <language>en-us</language>
      <pubDate><txp:article_custom section="event" limit="1" time="any" sort="LastMod desc"><txp:modified format="rfc822" gmt="1" /></txp:article_custom></pubDate>
      <lastBuildDate><txp:article_custom section="event" limit="1" time="any" sort="LastMod desc"><txp:modified format="rfc822" gmt="1" /></txp:article_custom></lastBuildDate>
      <docs>http://blogs.law.harvard.edu/tech/rss</docs>
      <generator>Textpattern</generator>
      <managingEditor>you@yoursite.com (Your Name)</managingEditor>
      <webMaster>you@yoursite.com (Your Name)</webMaster>
      <atom:link href="http://www.yoursite.com/feed" rel="self" type="application/rss+xml" />
<txp:article_custom time="any" form="feed_item" section="event" sort="LastMod desc" limit="10" />
   </channel>
</rss>

Building the Feed’s Metadata

Let’s explore the above code line by line. Everything of importance resides inside the <channel>.

  1. <title> is simply the name of the feed. Plain text, nothing fancy.
  2. <link> is the URL of your website (not the RSS feed). I used <txp:site_url /> for the sake of simplicity, but this can be hard-coded, like http://custom.sitename.com/or/whatever.
  3. <description> is pretty self-explanatory. Two or three sentences describing the content of the feed is all that is needed.
  4. <language> is the language of the feed. If you’re publishing from the States, en-us will suffice. Microsoft has a good list of most language codes.
  5. <pubDate> is when the feed was last modified. This is where we must get clever with TXP. We’ll use <txp:article_custom /> to pull the most recently modified article from the feed’s set of content. (In this case, it’s all articles published in the “event” section.) We’ll limit it to one, set the time to “any” to ensure we capture future-dated content, and then sort by the most recently modified, not the posted date. Inside the <txp:article_custom /> tag, <txp:modified /> renders the date and time of when the most recent article was published for the first time, or the last time it was edited. The RSS format uses RFC822 as its time stamp method, which Textpattern supports out of the box. This will produce a date in this format: Sun, 04 Apr 2010 12:29:55 GMT. Using RFC822 as the value of the format attribute helps us avoid building complicated date strings with strftime.
  6. <lastBuildDate> requires the same value as <pubDate>.
  7. <docs> is simply documentation of the RSS 2.0 format. You can use the link I referenced.
  8. <generator> is the name of the engine that built the feed. In this case, it’s our most favoritest CMS ever.
  9. <managingEditor> is the e-mail address and name of the feed’s content manager.
  10. <webMaster> can use the same value as <managingEditor>, or someone different.
  11. <atom:link /> is simply a self-referencing URI of the feed itself. Not required, but recommended.

That’s it! This is all the information a parsing engine needs to understand what your feed is, who is publishing it, and when it was last updated.

Building the Feed’s Items

Every actual article inside the feed is enclosed in the <item> tag. Feed items must appear after all of the metadata, so you cannot place something like the <pubDate> at the end of the XML. The last closing </item> tag must be the last thing before the closing </channel> tag.

We’ll use a standard <txp:article_custom /> tag to call our article content, and then our newly created article-type form feed_item to format that content. In addition, we must set time to “any” to capture future-dated content, specify where we are pulling the content (in this case, again, from the “event” section), sort by the last modified date starting with the most recent, and then limit the article count to whatever you’d like.

Inside the feed_item form, we’ll use this code:

<item>
   <title><txp:title /></title>
   <link><txp:permlink /></link>
   <guid><txp:permlink /></guid>
   <description><txp:excerpt /></description>
   <pubDate><txp:modified format="rfc822" gmt="1" /></pubDate>
</item>

Inside this form, we can use all of our standard article tags. To break it down:

  1. <title> is simply the title of the feed item. This, most likely, is also the title of your article.
  2. <link> is the URL of the feed item in question.
  3. <guid> stands for “globally unique identifier” and should be a unique URL for the feed item. In most cases, it’s simply the same value as <link>. Include both, because different parsing engines will use one or the other.
  4. <description> is, you know, the description. The value could also be <txp:body />, or whatever. (For instance, the feed for DeCal uses posted and expiration dates, custom fields, conditionals and more to render a complicated string of information.)
  5. <pubDate> uses the same last modified value as our metadata since the future-dated <txp:posted /> values are perceived as heretical by feed aggregators.

Testing the RSS 2.0 Feed

Once you’ve established your page and form template, it’s time to test. Simply type in http://www.yoursite.com/feed in Firefox, Opera or any other browser that renders XML nicely, and see what happens. If everything appears nicely, you’re probably solid.

XML is a very picky language. Unlike the liberal rendering engines of browsers that forgive pretty much any HTML sin short of first-degree JavaScript runtime errors, XML needs to be perfectly written with zero unencoded characters, unclosed tags, or other funny business. The best thing you can do is run your feed through feedvalidator.org this will tell you in no short order any problems you have. If you pass your feed through Feedburner, that service also provides a number of trouble-shooting tips.

2 Comments Comment feed

For feeds it is necessary to set the Content-Type as application/rss+xml or text/xml. For this purpose you can use plugin aks_header.

Simply add to beginning of feed_template page

<txp:aks_header name="Content-Type" value="application/rss+xml" nodebug="1" />

or for use gzip compression in feed:

<txp:aks_header name="Content-Type" value="application/rss+xml" strip="1" gzip="1" nodebug="1" />

Related article: your own RSS feed.

@makss — Great point, and nice follow-up. I was not sure if that was beyond the scope of the article so I left it out. An RSS feed will work if its encoded as HTML (it generates a warning, not an error), but if one wants a “complete” implementation, definitely a necessary step. Thanks!

Add a comment

Use Textile help to style your comments