Today I’ll show you how to read XML files using the NSXMLParser class. This can be very useful if you need to work with XML on your app.
The NSXMLParser class from the Foundation framework, gives us a way to read a XML file and get information that is relevant, using an event-driven approach. For each item (element, attributes, etc.) that it finds, the current delegate is notified and can process the correspondent data.
Suppose you have this XML:
<person>
<name>Jonh</name>
<age>23</age>
<facebook id="jonh.doe"/>
</person>
Let’s create a class that will read this XML and set the value of its properties according to it.
#import <Foundation/Foundation.h> @interface Person : NSObject <NSXMLParserDelegate> -(void) parseXML:(NSURL*)xmlUrl; @property NSString *name; @property int age; @property NSString *facebookId; @end
The Person interface is very straightforward. The most important thing about it is that it implements the NSXMLParserDelegate protocol. This protocol defines the methods that the NSXMLParser calls to notify when a XML item is found. The parseXML method receives a NSURL who points to the XML file that we need to parse.
Now, let’s see the Person class implementation. First, the parseXML method.
//... some code here
@property NSString *currentElement; //used by the delegate methods
@property NSString *ageString;
//... some code here
- (void) parseXML:(NSURL*) xmlUrl{
NSXMLParser *parser = [[NSXMLParser alloc] initWithContentsOfURL:xmlUrl];
parser.delegate = self;
[parser parse];
}
The first step is to create a NSXMLParser instance. Then we need to tell to the parser who is the delegate, in this case is the Person class itself. At the end, we call the parse method on the parser instance.
Obs:It is important to know that the parse method is synchronous so it will stop the thread that is calling it, until it returns.
It’s time we start working with the methods from the NSXMLParserDelegate protocol. The example below will show how we can get the XML information and use it to set values on our class properties.
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict {
self.currentElement = elementName;
if ([elementName isEqualToString:@"facebook"]){
self.facebookId = [attributeDict valueForKey:@"id"];
}
}
-(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{
if ([self.currentElement isEqualToString:@"name"])
self.name = [self.name stringByAppendingString:string];
else if ([self.currentElement isEqualToString:@"age"])
self.ageString = [self.ageString stringByAppendingString:string];
}
-(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{
if ([elementName isEqualToString:@"age"])
self.age = [self.ageString integerValue];
}
The method parser:didStartElement:namespaceURI:qualifiedName:attributes: is called when a new element is encountered. In our case, it will be called when the parser finds the elements person,name,age and facebook.
The facebook element has an attribute named id. When the parser finds this element, we will need to get the value of the id attribute. To do this, we use the attributeDict argument. This argument is a dictionary whose each key is the name of an attribute and each value is the corresponding attribute value.
The parser:foundCharacters: method is called to provide the contents of the current element (the one found by the parser:didStartElement:namespaceURI:qualifiedName:attributes
to the delegate. In our case, we use it to find the name and age of the person. Notice that the age property is an int so we’ll get its value on the last method.
The parser:didEndElement:namespaceURI:qualifiedName: method is sent by the parse when the element previously found is closed. In our code, we use this method to know that the </age> tag was found, and so we can cast the ageString property to its integer value.
Obs: Since there is only one line in the <age> tag, we could have done this at the parse:foundCharacters: method. I used it here to demonstrate the use of this method.
Conclusion
The NSXMLParser provides a simple way to work with XML files. The NXSMLParserDelegate has many other methods that are useful to extract and process information from XML. It can handle errors, CDATA, comments, and much more.To more information about these classes I recommend the iOS Developer library.
See you next time!
Wow, I don’t think I’ve ever found such a new blog before.