Creating an RSS and JSON driven app with Corona SDK

Haakon Langaas Lageng

While working on the Nyhetene app, an app that gathers more than 100 different rss feeds, we faced a few challenges that needed to be solved. Our biggest issues were related to loading external data, like rss feeds and json data, loading remote images, and displaying the results in a proper manner. We have solved problems related to parsing non US characters and the app crashing when asynch image loading returns. Monkeybin believes in clean, readable code, where logic is separated from display, so this series will follow some trusted OOP patterns to achieve that.

This post is aimed at developers using Corona SDK to build apps. All our code is object oriented, which (should) make it easy to take advantage of our classes in your own apps.

In this post, we will

  • Put together the building blocks for our app
  • Implement third party libraries like director, xmlparser and middleclass
  • Load an RSS feed
  • Parse the RSS feed
  • Display the RSS feed


Getting started

I start out with a basic setup, using director to manage the views. I have created a View_News.lua file, which will act as the main view. I renamed the director file to Lib_Director, and I have changed line 165 in the director file to function Lib_Director:changeScene(…) to make it work.

We have spent a great deal of time discussing and testing different ways to get a clean project root. Since Corona SDK don’t work with lua files inside folders, we have started to use an underscore convention file naming. It gives us a natural grouping of files and functionality, as you’ll see soon.

Our projects often contains a third party library called middleclass.lua. It brings some missing OOP features to the table. I have renamed the file to Lib_MiddleClass.lua. With middleclass loaded, we are able to create classes and objects, have private variables and functions etc. It took me some 3 minutes to get to know the library, well worth the time invested!

This particular project also needs an XmlParser, and I have used one I found at lua-users.org. I had to modify it to make it work with prefixed element names, and I added some utility functionality for extracting attribute values ++. You’ll find my version in the source code.

I will start out with the classes and parsing functionality. First out, I create a class to handle loading feeds:


UrlLoader = class("UrlLoader")

UrlLoader.callbackHandler = nil
UrlLoader.networkListener = nil

function UrlLoader:initialize(url, callback)
	UrlLoader.callbackHandler = callback
	network.request(url, "GET", UrlLoader.networkListener)

UrlLoader.networkListener = function(event)
	if event.isError then
		native.showAlert("Network Error", event.response, {"OK"})

A couple of things happens here. The first line is a Lib_MiddleClass function. It creates the object for us. The next two lines are MiddleClass’ way of defining private variabels. These variables will only be available to the UrlLoader class and cannot be reached by any other class in our app.

The function UrlLoader:initialize is also a special MiddleClass thingy. When you “new” this object, MiddleClass internally calls the initialize method. So if I were to create an instance of UrlLoader in my View_News.lua, I’d write UrlLoader:new(). Behind the scenes, MiddleClass calls the initialize method. That means the initialize method is actually the constructor, if you are familiar with that term.

The UrlLoader contructor takes two arguments. The first one, url, is the absolute url to the rss feed we want to load. The second argument is a delegate method. Since loading data with network.request is asynchronous, we must have a way of telling the parent class, in our case View_News, when the loading is completed, and return the loaded result.


SyndicationFeed = class("SyndicationFeed")

SyndicationFeed.items = nil
SyndicationFeed.title = nil

function SyndicationFeed:initialize(title)
	SyndicationFeed.title = title
	SyndicationFeed.items = {}

function SyndicationFeed:addItem(item)
	table.insert(SyndicationFeed.items, item)

function SyndicationFeed:parseFeed(xml)
	local parsed = XmlParser:ParseXmlText(xml)
	local channel = XmlParser:XmlNodes(parsed, "channel")
	local syndicationFeed = SyndicationFeed:new("NRK")
	for i, xmlNode in ipairs(channel) do
		if xmlNode.Name == "item" then
			local item = SyndicationItem:new(xmlNode)

function SyndicationFeed:getItems()
	return SyndicationFeed.items

function SyndicationFeed:getItem(i)
	return SyndicationFeed.items[i]

The SyndicationFeed class has a method for parsing xml to a SyndicationFeed, parseFeed(). It will traverse the xml file, loop through all the items, and build a table of SyndicationItem objects for us to use in the application. The data comes in as a raw string, so the first thing to do is to crunch it through the XmlParser:ParseXmlText method to create an xml object that we can navigate and extract data from.

Remember that the channel element in an rss xml contains a bunch of item elements? Putting the channel’s children in a variable give us something to loop through. Then I create an instance of my custom object SyndicationFeed. At this point, I am ready to loop through the items inside the channel variable.

Everytime the loop finds an xml element that is named “item”, I am creating a new SyndicationItem instance, and pass in the xml item.


SyndicationItem = class("SyndicationItem")

function SyndicationItem:initialize(node)
	self.title = XmlParser:XmlValue(node, "title")
	self.link = XmlParser:XmlValue(node, "link")
	self.description = XmlParser:XmlValue(node, "description")
	self.updatedDate = XmlParser:XmlValue(node, "a10:updated")
	local enclosure = XmlParser:XmlAttributes(node, "enclosure")
	if enclosure then self.enclosureUrl = enclosure.url end

The SyndicationItem is a lightweight object, taking care of it’s own extracting of data from the rss feed. It uses the XmlParser to assemble a title, link, description, updatedDate and image link – if it exists.


module(..., package.seeall)

function new()
	local g = display.newGroup()
	local callback = function(rss)
		local syndication = SyndicationFeed:new("NRK Feed")

		local items = syndication:getItems()
		for i=1, #items do
			local item = items[i]
			local itemGroup = display.newGroup()
			local title = display.newText(item.title, 10, 10, "Helvetica", 16)
			itemGroup.y = 10 + (40 * (i-1))
	UrlLoader:new("http://www.nrk.no/nyheter/siste.rss", callback)
	return g

Taking a look at View_News, you’ll see that a couple of things are going on. If you look down at the lower part of the code block, you see that I am instantiating the UrlLoader class from before, passing in the feed url and a callback delegate method. A few lines up, you find the delegate method itself. That method is being invoked when the UrlLoader has finished loading the feed! When that happens, a SyndicationFeed object is created and the feed gets parsed to SyndicationItems. Next in line is the logic to show the result on the device. I simply loop through the table of SyndicationItems inside the SyndicationFeed object, and writes their titles on the screen.


display.setStatusBar( display.HiddenStatusBar )

-- Libraries
local director = require("Lib_Director")

-- Classes

local mainGroup

local function main()
	mainGroup = display.newGroup()
	return true


Finally, I’m sewing it all together in the main.lua file. I load in the libraries and the classes, and use director to switch to the View_News view. And that’s it! Hope you’ve enjoyed the tutorial, and please check back for more as I continue to build out the app.

Disclaimer. I know I could have, and probably should have, separated stuff even more. Putting the parsing of xml inside the SyndicationFeed and SyndicationItem is not the “correct” way of doing it. But I don’t need any extra separation of concerns. This is all I need. YAGNI and KISS, two of my favourite programming principles weighs heavily on the choices I make.