Using NSXMLParser

Mon Jun 7 2010 | Mark Struzinski

---

This is my first stab at an iPhone project. I’m writing an app that consumes an RSS feed and parses it to retrieve a few bits of information for display on the screen. This is my first attempt at an implementation. Coming from a .NET background, it is quite a paradigm shift when switching to the heavily convention based world of Cocoa development.

If I was writing this app in .NET, I’d go out looking for the proper class libraries to parse the XML and begin framing out a class to perform all the functions I needed to populate an object to be persisted to the UI.

When researching the best way to do this, I found 2 prevalent methods of parsing XML in Cocoa:

I decided to go with NSXMLParser because it seemed like the path of least friction to get started with. NSXMLParser is a stream based reader. It basically reads the entire XML tree character by character and fires off events via delegate calls when it encounters useful information. I found this model very easy to use. After some trial and error, I’ve got it working well for my current project.

I am parsing the xml feed for Woot.com. The following is an abbreviated snippet of the elements I am interested in. The actual feed has a lot more info in it, but this should give you a feel for the structure:

Creating the Worker Class

NSXMLParser works using delegate callbacks to let you hook into events that
you are interested in. Most of the examples I found online used delegate methods
right inside the viewcontroller to accomplish the parsing. Since I have several
views which are going to take advantage of this functionality, I decided to
split it out into a worker class. Let’s construct this class
(I named it XMLParser) piece by piece:

I am initializing the class this way so I can populate the SaleItem inside of
XMLParser and still have access to it from the calling class (a ViewController)
when I’m done parsing.

Before we get into how to instantiate NSXMLParser and use it to parse a file,
let’s set up the delegate methods to get the data we need out of the file.

I usually put delegate methods at the bottom of the file, right after a
#pragma mark definition to delineate this group of methods from
the rest of the code. Hop down to the bottom of XMLParser.m, and place this
code just prior to @end:

Delegate Method

#pragma MARK - NSXMLParser Delegate Calls
// This method gets called every time NSXMLParser encounters a new element
-(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName
attributes:(NSDictionary *)attributeDict {
// If element is named "item", set bool to true so we know
// we are inside the element in other methods. This is needed
// because "item" contains most of the data we need
if ([elementName isEqualToString:ITEM]) {
[self setItemElementInProgress:YES];
}
}
// This method gets called for every character NSXMLParser finds.
-(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
// If currentValue doesn't exist, initialize and allocate
if (!currentValue) {
currentValue = [[NSMutableString alloc] init];
}
// Append the current character value to the running string
// that is being parsed
[currentValue appendString:string];
}

The final delegate method is fired when NSXMLParser reaches the end of an element. Here is the place we can be sure we have gotten the full value of the element, and can now persist that data to our model object for use. right after the foundCharacters method, add this method: