iOS:结合 SAX 和 DOM 解析

Posted

技术标签:

【中文标题】iOS:结合 SAX 和 DOM 解析【英文标题】:iOS: Combining SAX and DOM parsing 【发布时间】:2012-07-28 22:51:57 【问题描述】:

我目前正在处理一个 iPad 项目,我需要将大型 XML 文件处理到 SQLite 后端。我目前正在使用TBXML 解析器进行这项工作。

所以所有的逻辑都已经到位,并且通常 TBXML 解析器完成了它需要完成的工作。我现在遇到的唯一问题是 XML 文件变得太大并且内存不足。因此,我考虑切换到像 Alan Quatermain 的 AQXMLParser 这样的核心 NSXMLParser 之类的 SAX 解析器。然而,这将要求我重做我当前的所有逻辑,这些逻辑在某种程度上依赖于 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 编码的,我只会得到部分结果。但是当我纠正这一切时,一切顺利。内存使用并没有那么好。但也许它会尽其所能。需要运行更多测试...

【问题讨论】:

您的代码似乎有一些拼写错误。你能更新你的代码吗?会有帮助的 【参考方案1】:

总的来说,您的方法对我来说听起来不错。如果您的解决方案在没有性能问题的情况下为您工作,那么我不会太担心字符串处理。如果你愿意,你可以分析你的应用程序,看看这浪费了多少 CPU 时间。

如果您想做一些更优化的事情,您可以尝试找到一个 SAX 解析器,它可以为您提供原始缓冲区的字节偏移量,并将其与一个 DOM 解析器相结合,让您可以处理非空终止的 C 字符串。我相信这意味着您必须切换到 C 或 C++ 库。我已经使用rapidxml 来处理与您正在尝试的内容类似的东西(嵌入在大文件中的 xml 块)。

【讨论】:

好吧,使用 C(++) 库不是我喜欢的。所以我想我会实现这个版本,看看效果如何。 我认为从性能的角度来看它会很好,但请确保正确转义字符(即如果 '>' 出现在文本字符串中会发生什么情况)。此外,您上面的 sn-p 不处理属性等,但我假设您可以控制输入。 XML 本身相当简单。没有 CDATA 块(即使这不是问题,只是要实现的另一个委托方法)并且没有属性。不过,转义字符是一个好点!

以上是关于iOS:结合 SAX 和 DOM 解析的主要内容,如果未能解决你的问题,请参考以下文章

XML.03-DOM和SAX解析

XML文件解析DOM解析和SAX解析

XML 解析---dom解析和sax解析

Java web——xml文件读取的解析方式(DOM和SAX)

JAVA之DOM和SAX解析器

java解析XML① 之DOM解析和SAX解析(包含CDATA的问题)