As I've worked on populating jQueryBloggers, I've been surprised by how few blogs provide category specific RSS feeds. Almost every blog provides a basic RSS feed. That's pretty much a given. But for sites that cover multiple disparate topics, it's surprising how few will provide a RSS feed specific to one topic. I thought it might be fun to quickly explain how you could add support for category specific RSS feeds in your ColdFusion application. Obviously my implementation will be very specific to the data I'm using, but I still think it might be a useful bit of example code.

First, let's begin with a simple RSS feed example. I'll be using the cfbookclub datasource that ships with the ColdFusion sample applications. I set that up in my Application.cfc using one of the simplest, yet most welcome additions to ColdFusion 9.

component { this.name = "rsscat"; this.datasource = "cfbookclub"; }

In my index page I then created a link to the RSS page.

<a href="rss.cfm">RSS</a>

Now let's look at the actual RSS implementation in rss.cfm.

<cfquery name="getentries" maxrows="10"> select id, title, body, posted from blogentries order by posted desc </cfquery>

<cfset meta = {title="Main RSS", link="http://www.raymondcamden.com", description="Latest blog entries", version="rss_2.0"}>

<cfset colMap = {publishedDate="posted",content="body"}>

<cffeed action="create" query="#getentries#" properties="#meta#" columnmap="#colMap#" xmlvar="rssXML">

<cfcontent type="text/xml" reset="true"><cfoutput>#rssXML#</cfoutput>

I begin with a simple query to get my blog entries. Notice I've sorted them newest to oldest. I've used maxrows to restrict the number of entries to 10. That seems to be fairly standard for RSS feeds but you can use any value really. Next up is a structure called meta. In order to create a RSS feed there are a few basic things you need to define. I've set a title, link, description, and version for my feed.

The colMap structure is simply an alias. RSS feeds have specific column requirements. This let's me tell ColdFusion to map a RSS column to one of my columns.

Next - I actually create the feed and store it into an xml variable. Finally I output it. And that's that. I've complained a few times about bugs and issues in cffeed, but you have to appreciate how simple this template is.

Ok - so now let's talk category specific feeds. I began by writing some simple code to get categories from the database. I then used this query to create a list of RSS links:

<cfquery name="getcats"> select categoryid, categoryname from blogcategories order by categoryname desc </cfquery>

<cfoutput query="getcats"> <a href="rss2.cfm?catid=#categoryid#">#categoryname# Feed</a><br/> </cfoutput>

I assume there isn't anything weird there so I'll just move on. Let's look at rss2.cfm.

<cfparam name="url.catid" default=""> <cfquery name="getentries" maxrows="10"> select id, title, body, posted from blogentries <cfif url.catid neq ""> where id in ( select entryidfk from blogentriescategories where categoryidfk = <cfqueryparam cfsqltype="cf_sql_varchar" value="#url.catid#"> ) </cfif> order by posted desc </cfquery>

<cfif url.catid is ""> <cfset meta = {title="Main RSS", link="http://www.coldfusionjedi.com", description="Latest blog entries", version="rss_2.0"}> <cfelse> <!--- grab the category name ---> <cfquery name="getcat"> select categoryname from blogcategories where categoryid = <cfqueryparam cfsqltype="cf_sql_varchar" value="#url.catid#"> </cfquery>

<cfset meta = {title="RSS for #getcat.categoryname#", link="http://www.coldfusionjedi.com", description="Latest blog entries for #getcat.categoryname#", version="rss_2.0"}>

</cfif>

<cfset colMap = {publishedDate="posted",content="body"}>

<cffeed action="create" query="#getentries#" properties="#meta#" columnmap="#colMap#" xmlvar="rssXML"> <cfcontent type="text/xml" reset="true"><cfoutput>#rssXML#</cfoutput>

I'm going to focus on how this template differs from the previous version. I start off by paraming a value for catid. I want my template to support both the core RSS feed as well as the category specific one. I modify my query to allow for this. I know (or at least think I know) that subselects like that aren't very performant, but for now, it works.

The next change is to the metadata I provide for my RSS feed. I want it to be clear that the category specific feed is different. You can see see here that I fetch the category name and then use it in my values. I'd also probably have a category specific link. For now though I just changed the title and description.

The rest of the code is the exact same. Define my column map - create my XML - serve it up. Not that it's terribly exciting, but you can demo this below.

Any questions?