A Simple Quick Reusable XML Parser For The iPhone
I found that I was needing an XML parser for nearly every iPhone application I was writing. Once you figure out the streaming nature of NSXMLParser, it really isn’t very difficult to use. However, since I was always having the didStartElement/foundCharacters/didEndElement functions in each application, I really wanted to break them out into a reusable class.
I found that most my XML implementations were VERY simple, as I was just using it for data storage and transfer. However, of course, each XML is different so my class has to handle that properly.
After making several iterations, I settled on using an NSArray for the root of the XML file. Each node is a NSDictionary with three object/key pairs:
- element – This is the element name
- data – This is the string data in the element
- children – This is an NSArray of the children
So a basic usage would be to let it parse your XML, then walk thru the array you get back filling up your internal data structures with the information you need. You can dump the XML to the debug console with simple code like this:
NSURL *URL=[[NSURL alloc] initWithString:@"http://www.w3schools.com/XML/cd_catalog.xml"]; SimpleXMLParser* thisParser = [[SimpleXMLParser alloc] initWithURL:URL]; [URL release]; [thisParser parse]; [thisParser dumpRoot];
The dumpRoot function is implemented as two functions as so:
- (void) dumpArrayRecursive: (NSArray*) inArray parentElement:(NSString*)inParent
{
for (int i=0;i<[inArray count];i++)
{
NSDictionary* thisDict = [inArray objectAtIndex:i];
NSLog(@"Element: %@ Data: %@ Parent: %@", [thisDict objectForKey:@"element"], [thisDict objectForKey:@"data"], inParent);
[self dumpArrayRecursive:[thisDict objectForKey:@"children"] parentElement:[thisDict objectForKey:@"element"] ];
}
}
- (void) dumpRoot
{
[self dumpArrayRecursive:theMainStack parentElement:@"Root"];
}
I am sure many improvements could be made, so feel free to be vocal in the comments section. I am fairly new to Objective-C and don't feel I have a real grasp of memory management. I am SURE I am leaking quite a bit. I figure I should be walking through the root array recursively releasing each dictionary, and each array on each dictionary. But I havn't implemented that yet...so... beware of that. Or maybe I could use some internal garbage collection to do it for me? I don't know really...any suggestions would be fantastic.
At any rate, this is a good example of a simple XML parser. No it isn't going to work in all cases, but it is reusable, so it beats re-implementing the streaming parser each time!
Here is the code: SimpleXMLTest.zip





Great post! I tried out the XML parser and it works great! I did add the following line to didStartElement in order to save the attributes:
[newDict setObject:attributeDict forKey:@"attributes"];
Other than that, this is very useful, thanks for posting!
Good work mate. I was looking for something similar and your solution just worked great for me.
Doesn’t work in simulator with iOS 4.3