我目前正在处理一个 iPad 项目,我需要将大型 XML 文件处理到 SQLite 后端。我目前正在使用TBXML解析器进行这项工作。
所以所有的逻辑都已经到位,并且通常 TBXML 解析器完成了它需要做的工作。我现在遇到的唯一问题是 XML 文件变得太大并且内存不足。因此,我考虑切换到 SAX 解析器,例如 Alan Quatermain 的AQXMLParser之类的核心 NSXMLParser 。然而,这将要求我重做我当前的所有逻辑,这些逻辑在某种程度上依赖于 DOM 树提供的功能。这是我宁愿不做的事情。
所以我想要尝试并做的是创建一种混合方法。鉴于我的 XML 结构,这应该是可能的。它基本上是一些重复的“记录”元素。在每条记录中都有可以重复和嵌套的各种元素。在我目前的方法中,我解析文档并将每个记录元素传递给将其处理到数据库中的函数。鉴于这已经存在,我想在我的混合解析方法中使用它。
这就是我想要实现的。我使用 SAX 解析器遍历我的文档。在遍历文档时,我构建了一个 Record 元素。每当我完成一个记录元素时,我都会将它传递给使用 TBXML 处理它的现有函数。然后 SAX 解析器继续构建下一个记录元素。主要目标是: - 修复内存占用(它不需要尽可能小,但它必须保持不变或至少比使用 TBXML 更小) - 保持性能可接受。
目前想实现这个如下:
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName attributes:(NSDictionary *)attributeDict{
//Recreate record string each time record element is encountered
if([elementName isEqualToString:@"Record"]) record = [[NSMutableString alloc] init];
//Write XML tag with name
[record appendFormat@"<%@>, elementName];
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{
//Write XML content
[record appendString:string];
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{
//Write XML tag
[record appendFormat@"</%@>, elementName];
if([elementName isEqualToString:@"Record"]){
//Parse record string into TBXML object
TBXML * tbxmlRecord = [TBXML tbxmlWithXMLString:record];
//Send it to the TBXML record processor
[self processElement:tbxmlRecord.rootXMLElement];
}
}
我认为这应该可行,但使用字符串感觉很脏。此外,当解析器到达新的记录元素时,我担心记录字符串是否不会很快被覆盖。
所以我的问题是,如果这是解决这个问题的合理方法,或者是否有更好的方法让我实现我正在寻找的东西?
编辑: 我已经实现了这种方法,它看起来工作得很好。我遇到的唯一问题是,如果我的源文件不是 UTF-8 编码的,我只会得到部分结果。但是当我纠正这一切时,一切顺利。内存使用并没有那么好。但也许它会尽其所能。需要进行更多测试...