I'm parsing an XML file and filling a table view. The XML has a format like this:
<article>
<title>Title 1</title>
<last-modified>MM/DD/YYY</last-modified>
</article>
...
I currently have it working using an NSMutableString
to collect all of the a开发者_高级运维rticle titles and appending the strings in the - (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
method. Then at the appropriate time I'm adding the articleTitle
to an NSMutableArray
that holds all article titles, and filling the table from the array, as you'd expect.
However, now I want to switch to using a table view cell that has a subtitle (I want to put the last-modified date as the detailTextLabel
and the title as the textLabel
). With the way the parsing is split up into several methods (i.e. 2 parser
methods and the foundCharacters
method), I'm not sure how I should go about "collecting" the data, and filling the table from that data.
What's the best approach for this? Can I somehow just fill an NSDictionary or something, and just retrieve the items by key when building out the table cells?
I can't seem to figure out the best way to deal with this.
Thanks in advance!
You could go with a DOM parser if you like, and it might make your life a bit easier, but if for some reason you want to stick with NSXMLParser, keep reading.
You want the object you give the parser as your delegate (the thing that implements NSXMLParserDelegate) to basically accumulate the data as it is handed the data.
IMPORTANT DETAIL OFTEN OVERLOOKED: For the 'content' of the various tags you can actually receive multiple calls to parser:foundCharacters:
. There is absolutely no requirement that the parser hand it all to you at once. If it wanted to, it could send you one character at a time and you'd have to properly handle it.
The following assumes the following ivars:
NSMutableArray articles_;
NSMutableString currentCharacters_;
Article currentArticle_; // Article has title and lastModified properties.
And here's a sample of how the delegate could implement a few relevant messages (the following code obviously has no error handling):
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict {
if ([elementName isEqualToString:@"article"]) {
NSAssert(currentArticle_ == nil, @"Uh oh! Bad XML!");
currentArticle_ = [[Article alloc] init];
return;
}
if ([elementName isEqualToString:@"title"]) {
NSAssert(currentCharacters_ == nil, @"Uh oh! Bad XML!");
currentCharacters_ = [[NSMutableString alloc] init];
return;
}
if ([elementName isEqualToString:@"last-modified"]) {
NSAssert(currentCharacters_ == nil, @"Uh oh! Bad XML!");
currentCharacters_ = [[NSMutableString alloc] init];
return;
}
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
if ([elementName isEqualToString:@"article"]) {
[articles_ addObject:currentArticle_];
[currentArticle_ release], currentArticle_ = nil;
return;
}
if ([elementName isEqualToString:@"title"]) {
currentArticle_.title = currentCharacters_;
[currentCharacters_ release], currentCharacters_ = nil;
return;
}
if ([elementName isEqualToString:@"last-modified"]) {
[currentArticle_ setLastModifiedWithString:currentCharacters_];
[currentCharacters_ release], currentCharacters_ = nil;
return;
}
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
[currentCharacters_ appendString:string];
}
You can read an official Event-Driven XML Programming Guide and the tutorial
Also I can suggest to try touchXML instead of NSXMLParser
I user a DOM Parser, it is cleaner, and easier if you are not parsing alot of data.. recommend Google's GDATA
here is a StackOverflow Question on it
NSError *error;
GDataXMLDocument *doc = [[GDataXMLDocument alloc] initWithData:xmlData options:0 error:&error];
if (doc == nil) { return nil; }
// get number of hits
GDataXMLElement * article = [[doc nodesForXPath:@"//article" error:nil] objectAtIndex:0];
// title
NSLog([[[entry elementsForName:@"title"] objectAtIndex:0] stringValue]], nil);
// last-modified
NSLog([[[entry elementsForName:@"last-modified"] objectAtIndex:0] stringValue]], nil);
精彩评论