Parse Nested XML Objective C - NSXMLParser
All,
I have XML in the following format:
<linked-list>
<Description>
<desc></desc>
<IP></IP>
</Description>
</linked-list>
This XML statement could have an infinite number of <Description></Description> inside of the <linked-list></linked-list>.
How should I parse this using NSXMLParser? My current code is as follows, but it parses incorrectly.
@implementation XMLParser
@synthesize response;
- (XMLParser *) initXMLParser
{
self = [super init];
// init dictionary of response data
response = [[NSMutableDictionary alloc] init];
return self;
}
//Gets Start Element of SessionData
- (void)parser:(NSXMLParser *)parser
didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qualifiedName
attributes:(NSDictionary *)attributeDict
{
if ([elementName isEqualToString:@"linked-list"])
{
NSLog(@"Found linked-list in the return XML! Continuing...");
//response is a NSMutableArray instance variable
//THIS SHOULD NEVER NEED TO BE USED
if (!response)//if array is empty, it makes it!
{
NSLog(@"Dictionary is empty for some reason, creating...");
response = [[NSMutableDictionary alloc] init];
}
//END: THIS SHOULD NEVER BE USED
return;
}
else
{
currentElementName = elementName;
NSLog(@"Current Element Name = %@", currentElementName);
return;
}
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
if (!currentElementValue) {
// init the ad hoc string with the value
currentElementValue = [[NSMutableString alloc] initWithString:string];
} else {
[currentElementValue setString:string];
NSLog(@"Processing value for : %@", string);
}
}
//Gets End Element of linked-list
- (void)parser:(NSXMLParser *)parser
didEndElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName {
if ([elementName isEqualToString:@"linked-list"])
开发者_JAVA百科 {
// We reached the end of the XML document
// dumps dictionary into log
NSLog(@"Dump:%@", [response description]);
return;
}
else
{
//Adds key and object to dictionary
[response setObject:currentElementValue forKey:currentElementName];
NSLog(@"Set values, going around again... brb.");
}
currentElementValue = nil;
currentElementName = nil;
}
@end
Some observations:
An infinite number of WHAT inside of the WHAT?
Assuming there can be more than one
Description
element, the outer data structure in which you store the contents must be aNSMutableArray
, not a dictionary. You then use one mutable dictionary perDescription
element.Consequently, in
didStartElement:
, check if the element name is@"Description"
and if so, create a newNSMutableDictionary
instance that you store in an ivar.In
foundCharacters:
, you always have to append the new characters to the existingcurrentElementValue
because the method can be called multiple times for each element's contents. I see many people do this wrong despite the fact that Apple's sample code clearly demonstrates the correct way.In
didEndElement:
, do this:If the element name is
@"desc"
or@"IP"
, assigncurrentElementValue
to the corresponding key in your current mutable dictionary. Don't forget to releasecurrentElementValue
before you set it tonil
. You currently have a memory leak in your code because you're not doing that.If the element name is
@"Description"
, add the current mutable dictionary to the mutable array. Release the dictionary and set the ivar tonil
. A new dictionary will be created the next time you encounter a@"Description"
element indidStartElement:
.If the element name is
@"linked-list"
, the mutable array will contain all the dictionaries and you're done.
精彩评论