Friday, January 18, 2013

Parsing XML data with NSXMLParser


Objective C NSXMLParser is an event driven parser. When an instance of this class pareses an XM document it notifies its delegate about the items (elements, attributes, etc) that it encounters during XML processing. 

XML document structure used in this example:

<users>
 <user>
  <userName>AAaa</userName>
  <firstName>AA</firstName>
  <lastName>aa</lastName>
 </user>
 <user>
  <userName>BBbb</userName>
  <firstName>BB</firstName>
  <lastName>bb</lastName>
 </user>
...
</users>




Create a delegate for NSXMLParser

Let's create a delegate for the parser XMLParser.h - it implements the three events reported by NSXMLParser object:

#import <Foundation/Foundation.h>

@class User;
@interface XMLParser : NSObject {
NSMutableString *currentElementValue; // an ad hoc string to hold element value
User *user; // user object
NSMutableArray *users; // array of user objects
}

@property (nonatomic, retain) User *user;
@property (nonatomic, retain) NSMutableArray *users;

- (XMLParser *) initXMLParser;

@end

The delegate implementation – XMLParser.m file:

#pragma mark Parse the start of an element
#pragma mark -

- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qualifiedName
attributes:(NSDictionary *)attributeDict {
if ([elementName isEqualToString:@"user"]) {
NSLog(@"user element found – create a new instance of User class...");
user = [[User alloc] init];
//We do not have any attributes in the user elements, but if
// you do, you can extract them here:
// user.att = [[attributeDict objectForKey:@"<att name>"] ...];
}
}

#pragma mark Parse an element value
#pragma mark -

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
if (!currentElementValue) {
// init the ad hoc string with the value
currentElementValue = [[NSMutableString alloc] initWithString:string];
} else {
// append value to the ad hoc string
[currentElementValue appendString:string];
}
NSLog(@"Processing value for : %@", string);
}

#pragma mark Parse the end of an element
#pragma mark -

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName {
if ([elementName isEqualToString:@"users"]) {
// We reached the end of the XML document
return;
}
if ([elementName isEqualToString:@"user"]) {
[users addObject:user];
// release user object
[user release];
user = nil;
} else {
[user setValue:currentElementValue forKey:elementName];
}
[currentElementValue release];
currentElementValue = nil;
}

NSXMLParser call example

NSData *data contains our XML document.

#import "XMLParser.h"

- (void) doParse:(NSData *)data {
NSXMLParser *nsXmlParser = [[NSXMLParser alloc] initWithData:data]; // create and init NSXMLParser object
XMLParser *parser = [[XMLParser alloc] initXMLParser]; // create and init our delegate
[nsXmlParser setDelegate:parser]; // set delegate
BOOL success = [nsXmlParser parse]; // parsing...
if (success) {
NSLog(@"No errors - user count : %i", [parser [users count]]);
// get array of users here
NSMutableArray *users = [parser users];
} else {
NSLog(@"Error parsing document!");
}
[parser release];
[nsXmlParser release];
}




2 comments:

xml guy said...

thansk bharat, looks really useful, could i mention iton my blog to my readers also?

mahes waran said...

with my pleasure !!