I've complained (quite a bit) about some of the warts around the CFFEED tag. Looks like my complaining may have helped a bit. ColdFusion 9 adds a new feature to CFFEED that I think is pretty darn nice.

Previously, if you tried to create a feed and it contained "bad" characters (Microsoft Smart Quotes, etc), then you ended up with invalid XML. Here is a simple example.

First, I'll create a feed with one entry. The entry content is contained in a file called bad.txt:

Here is the code I used to include and create a feed from the text file.

<cfscript> // Create the feed data structure and add the metadata. myStruct = {}; mystruct.link = "http://www.coldfusionjedi.com"; myStruct.title = "My Blog"; mystruct.description = "It wears sunglasses at night"; mystruct.pubDate = Now(); mystruct.version = "rss_2.0";

/* Add the feed items. A more sophisticated application would use dynamic variables and support varying numbers of items. */ myStruct.item =[]; myStruct.item[1] = {}; myStruct.item[1].description = {}; myStruct.item[1].description.value = fileRead(expandPath("../bad.txt")); myStruct.item[1].link = "http://www.cnn.com";

myStruct.item[1].pubDate = Now(); myStruct.item[1].title = "Title";

</cfscript>

<cffeed action = "create" name = "#myStruct#" escapechars="false" xmlVar = "myXML">

<cfoutput> #htmlCodeFormat(myXML)# </cfoutput>

This is standard CFFEED stuff, so I won't describe each line. I don't normally make feeds this way though - normally I create it from a query. Note that I've included escapechars, and set it to false, which makes it match ColdFusion 8 behavior. The result is a bit funky:

Switching escapechars to true though results in:

Nice. There are other ways to handle this but this is certainly a bit simpler.

There is another new ColdFusion 9 that indirectly helps CFFEED as well. One of the things I do at ColdFusionBloggers is called a HTTP Conditional Get. This is basically a 'smart' HTTP call in that I can say: "Hey URL, I last hit you at 5PM, if you haven't updated, send me a nice short message, otherwise send me all your data." This helps streamline some of the network traffic I incur when fetching 500+ RSS feeds. However, there is a problem. If the data is new, and I get the RSS XML back, I have it in a variable. CFFEED only supports parsing URLs and files, it doesn't support parsing a string. This is a bit silly, but, it is what it is.

However - in ColdFusion 9 we now have a RAM based file system called the VFS (Virtual File System). I can use this as a temporary storage for the XML, and point CFFEED at it. Here is a trivial example:

<cfset source = "http://feedproxy.google.com/RaymondCamdensColdfusionBlog"> <cfhttp url="#source#"> <cfset randFileName = "ram:///#createUUID()#.txt"> <cfset fileWrite(randFileName, cfhttp.filecontent)>

<cffeed action="read" source="#randFileName#" query="feed"> <cfdump var="#feed#" top="1">

<cfset fileDelete(randFileName)>

I begin by grabbing my RSS feed. I want to save it to the VFS and so I just pick a random file for the name. I then point CFFEED at it and convert the RSS into a query. At the end, I clean it up by deleting the file.