我已经熟悉了iPhone SDK中的NSXMLParser,但我觉得它的事件驱动性质对我来说很尴尬。我只是想提取一些元素值,但是这个必须处理startElement,foundCharacters和endElement的概念似乎比实际应该更多的工作。我只是以错误的方式看待这个问题,还是在iPhone SDK中使用更简单的基于树/ DOM的XML方式?
如果建议只是使用NSXMLParser,是否有某些设计模式可以用来使我的代码在startElement方法中保持5级嵌套ifs?
答案 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)
请考虑以下代码段,该代码段使用libxml2,Matt Gallagher's libxml2 wrappers和Ben Copsey's ASIHTTPRequest来解析XML文档。
nodes
类型的NSArray*
实例将包含NSDictionary*
个对象,您可以递归解析这些对象以获取所需的数据。
或者,如果您了解XML文档的方案,则可以编写XPath查询以直接获得nodeContent
或nodeAttribute
值。
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所做的。