在iPhone上进行XML解析的最佳方法

时间:2009-05-08 23:49:48

标签: iphone objective-c

我已经熟悉了iPhone SDK中的NSXMLParser,但我觉得它的事件驱动性质对我来说很尴尬。我只是想提取一些元素值,但是这个必须处理startElement,foundCharacters和endElement的概念似乎比实际应该更多的工作。我只是以错误的方式看待这个问题,还是在iPhone SDK中使用更简单的基于树/ DOM的XML方式?

如果建议只是使用NSXMLParser,是否有某些设计模式可以用来使我的代码在startElement方法中保持5级嵌套ifs?

3 个答案:

答案 0 :(得分:10)

如果你在iPhone上,使用基于树的解析可能是一个令人望而却步的内存耗尽。相信我,我一直在那里,并且在我的主要iPhone应用程序开发的最后五个月里我尝试了许多不同的方法。基于树的解析工作正常,直到您下载包含400条非常长的注释的某人​​的评论流,大约600KB的原始数据。除了生成的XML树的大小之外,在创建该树时内部分配的内存可能是巨大的。

我最终创建了一个NSXMLParser的变体,它从提供的NSInputStream中提取数据,而不是使用单个数据块,并且一次只传递1KB到libxml进行处理(NSXMLParser也使用libxml,但传递了100%的数据)一气呵成)。

源代码可用on github(查看StreamingXMLParser文件夹)。你还会在那里找到一个委托超类;对于大多数解析需求,您可以继承AQXMLParserDelegate并在子类中实现-start[Element]WithAttributes: (NSDictionary *) attrs-end[Element]。这些方法将作为start& amp;发现结束标记,在结束标记内,您可以使用self.characters来访问元素的内容字符或CDATA。

有关不同解析器(尽管在Mac上,而不是iPhone)的相对内存占用的更多信息,请参阅我的原始博客帖子here以及NSXMLDocument here的后续内容。

答案 1 :(得分:1)

请考虑以下代码段,该代码段使用libxml2Matt Gallagher's libxml2 wrappersBen Copsey's ASIHTTPRequest来解析XML文档。

nodes类型的NSArray*实例将包含NSDictionary*个对象,您可以递归解析这些对象以获取所需的数据。

或者,如果您了解XML文档的方案,则可以编写XPath查询以直接获得nodeContentnodeAttribute值。

ASIHTTPRequest *request = [ASIHTTPRequest alloc] initWithURL:[NSURL URLWithString:@"http://stackoverflow.com/"];
[request start];
NSError *error = [request error];
if (!error) {
    NSData *response = [request responseData];
    NSLog(@"Root node: %@", [[self query:@"//" withResponse:response] description]);
}
else 
    @throw [NSException exceptionWithName:@"kHTTPRequestFailed" reason:@"Request failed!" userInfo:nil];
[request release];

...

- (id) query:(NSString *)xpathQuery withResponse:(NSData *)respData {
    NSArray *nodes = PerformXMLXPathQuery(respData, xpathQuery);
    if (nodes != nil)
        return nodes;
    return nil;
}

答案 2 :(得分:0)

从Seismic XML重新利用代码提供了一个非常好的API,可以从XML创建NSObject子类。

  

如果建议只是使用NSXMLParser,我是否可以使用某些设计模式来使我的代码在startElement方法中保持5级嵌套ifs?

我取决于你想要做什么。您可以将元素名称放在字典中,并根据字典中的相关对象执行操作 - 这实际上就是SeismicXML所做的。