Almost any time you’ll need to pull some data from the web. Using Objective-C you have at your disposal a pretty good XML parser – the event-based version. What really means is that instead of building in-memory tree with the structure of the XML you’ll have some events raised when the parser encounters a special token – the most usual ones are tag start, tag end and found comments. The parsing goes node by node and is not nesting-sensitive. As soon as the parser returns you a node, you don’t know where in the structure you are currently anymore. As long as you have a clearly defined structure where each element is always present, you could do this using a counter. However, as soon as you have multiple nodes with no defined count, you have a problem.
The usage is simple and straight-forward. For simplicity, we assume that we have only have one level of children under the root node, but this can be easily extended to many levels. We’ll see some code and after that the detailed explanations:
- (void)parseJourneyData:(NSData *)data parseError:(NSError **)err { // create and allocate the parser - it must be initiated with the XML data that we received or loaded NSXMLParser *xmlParser= [[NSXMLParser alloc] initWithData:data]; self.arrResult= [[NSMutableArray alloc] init]; // Create the array for holding the resulted data [xmlParser setDelegate:self]; // The parser calls will be redirected to methods in this class [xmlParser setShouldProcessNamespaces:NO]; // We are not interested in namespaces [xmlParser setShouldReportNamespacePrefixes:NO]; // neither in prefixes [xmlParser setShouldResolveExternalEntities:NO]; // just data, no other stuff [xmlParserparse]; // Parse that data.. here the parsing begins and the delegated methods will get called //the parsing process ended and we check for errors if (err && [xmlParser parserError]) { *err = [xmlParser parserError]; } [xmlParser release]; //cleaning the remainders }
The next step is to implement the delegate methods. The easiest way to find them is to start the help system of XCode – while in IDE, keep the Alt key pressed until the cursor transforms into an cross and then double click on the element for which help is required, in our case NSXMLParser. In the window that appears, you’ll find easily the methods declarations as follows and you’ll notice that they are pretty descriptive by themselfs:
- (void)parser:(NSXMLParser *)parser idStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict; - (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string; - (void)parser:(NSXMLParser *)parser idEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName;
Now let’s fill them with some code:
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict { if (qName) { elementName = qName; } // alloc the current property self.currentProperty = [NSMutableString string]; } - (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string { if (self.currentProperty) { [currentProperty appendString:string]; } } - (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName { if (qName) { elementName = qName; } [arrResult addObject:self.currentProperty]; // We reset the currentProperty, for the next textnodes.. self.currentProperty = nil; }
That’s pretty much it. Happy coding!