XMLReader 是 SAX 解析器、DOM 解析器,还是两者都不是?

Posted

技术标签:

【中文标题】XMLReader 是 SAX 解析器、DOM 解析器,还是两者都不是?【英文标题】:Is XMLReader a SAX parser, a DOM parser, or neither? 【发布时间】:2011-03-04 04:03:57 【问题描述】:

我正在测试各种方法来读取 php 中的 XML 配置文件(可能很大,读取非常频繁)。从来不需要写作。我有两个成功的实现,一个使用 SimpleXML(我知道这是一个 DOM 解析器),一个使用 XMLReader

我知道 DOM 读取器必须读取整个树,因此会占用更多内存。我的测试反映了这一点。我也知道 SAX 解析器是一个“基于事件”的解析器,它使用较少的内存,因为它从流中读取每个节点而不检查下一个节点。

XMLReader 还从带有光标的流中读取,提供有关它当前所在节点的数据。因此,听起来 XMLReader (http://us2.php.net/xmlreader) 绝对不是 DOM 解析器,但我的问题是,它是 SAX 解析器还是其他什么?看起来 XMLReader 的行为方式与 SAX 解析器的行为方式相同,但不会自己抛出事件(换句话说,您可以使用 XMLReader 构造 SAX 解析器吗?)

如果是别的东西,它所在的分类有名字吗?

【问题讨论】:

另见this question,答案有基准链接 参见this other related question,关于使用 LibXML2 实现,以及使用 SAX 接口 而不是 Expat 接口...以及关于现在的术语问题(这里比较混乱,那里更好)。 【参考方案1】:

XMLReader calls itself a "pull parser."

XMLReader 扩展是一个 XML Pull 解析器。阅读器充当文档流上的光标,并在途中的每个节点处停止。

它后来继续说它使用libxml。

This page on Java XML Pull Parsing 可能会引起一些兴趣。如果 XMLReader 与该项目的目标和意图相关,那么您的问题的答案完全属于“两者都不是”类别。

【讨论】:

【参考方案2】:

SAX 解析器是实现 SAX API 的解析器。也就是说:给定的解析器是 SAX 解析器当且仅当您可以使用 SAX API 对其进行编码。对于 DOM 解析器也是如此:这种分类纯粹是关于它支持的 API,而不是如何实现该 API。因此,SAX 解析器也很可能是 DOM 解析器。因此你不能确定使用更少的内存或其他特性。

但要解决真正的问题:XMLReader 似乎是更好的选择,因为它是一个拉式解析器,您可以非常明确地请求您想要的数据,因此所涉及的开销应该更少。

【讨论】:

【参考方案3】:

XMLReader 是 SAX2 解析器必须实现的接口。因此,当您通过XMLReader 访问它时,您可以说您有一个 SAX 解析器,简而言之,XMLReader 就是 SAX 解析器。

请参阅javadoc of XMLReader。

XMLReader 是 XML 解析器的 SAX2 驱动程序必须实现的接口。此接口允许应用程序在解析器中设置和查询特性和属性,注册用于文档处理的事件处理程序,并启动文档解析。

我认为这些信息是相关的,因为:

来自 SAX 官方网站 即使 javadoc 用于 Java,SAX 也起源于 Java 语言。

【讨论】:

不,这是错误的。 PHP XMLReader 是一个拉式解析器,而Java XMLReader 是一个基于事件的推式解析器。因此,PHP XMLReader 既不是 SAX 解析器也不是 DOM 解析器。 您应该将您的评论放在正确的位置,即在 OP 问题下。 是的,但我试图指出 OP 是在谈论 PHP,而不是 Java。 Java XMLReader 和它的接口是完全不同和无关的。 好的,我没有认真阅读这个问题,接受的答案让我专注于 Java。我的坏【参考方案4】:

简而言之,两者都不是。

SAX 解析器是面向流、基于事件的推送解析器。您注册回调函数来处理诸如 startElement 和 endElement 之类的事件,然后调用 parse() 来处理整个 XML 文档,一次一个节点。据我所知,PHP 没有维护良好的 SAX 解析器。但是,有XMLParser,它使用了非常相似的Expat 库。

DOM 解析器要求您将整个 XML 文档加载到内存中,但它们提供了一个面向对象的 XML 节点树。 PHP 中的 DOM 解析器示例包括 SimpleXML 和 DOM。

PHP XMLReader 不是这些。它是一种面向流的“拉解析器”,需要您创建一个大循环并调用 read() 函数将光标向前移动,一次处理一个节点。

XMLParser 和 XMLReader 与 SimpleXML 和 DOM 相比的最大优势在于面向流的解析器具有内存效率,仅将当前节点加载到内存中。另一方面,SimpleXML 和 DOM 更易于使用,但它们需要您将整个 XML 文档加载到内存中,这对于非常大的 XML 文档是不利的。

【讨论】:

Ops,我知道 PHP 的 SAX XML Parser,另请参阅 my answer explaning it。 @PeterKrauss,这是一个不准确的说法。引用您链接到的XML Parser doc……“这个 PHP 扩展实现了对 James Clark 在 PHP 中的 expat 的支持。”并引用Expat Wikipedia page,“Expat 不是符合 SAX 的解析器。”当然,也有实现 SAX 和 SAX2 接口的3rd-party wrappers for Expat。 PHP 的 XML Parser 没有实现 SAX 接口,尽管它非常相似。 是的......并且不准确始于 PHP 指南(!),没有引用术语“SAX”(this author say that it is SAX),并且在引用 expat 时没有说它是“外籍界面”还是“原始旧外籍软件”。 PHP-Guide 的另一部分说使用 LibXML2,LibXML2 page 说实现了 SAX:“类似于 SAX2 的接口和与早期 expat 版本兼容的最小 SAX1 实现”。这是模棱两可的...... 不,你错了。 Java org.xml.sax 包是SAX 的规范 实现。 PHP XML Parser interface 是否跟随 Java org.xml.sax interface?不,不是的。例如,PHP XML Parser 没有 startDocument 和 endDocument 事件处理程序。因此,PHP XML Parser SAX 兼容。故事结束。 “SAX 最初是仅 Java 的 API...1998 年代”,仅 Java starts the history (!)。 SAX 不是 Java 概念,Java/Oracle 也不是“SAX 所有者”。 SAX 是 XML 解析的通用抽象,是 DOM 的替代品...所以,Oracle 的 org.xml.sax 或许对 Java 用户来说是不错的,并且是一个很好的“参考模型”,但是不是像 W3C 那样的standard body。所以,请不要radicalize,讨论。你有很好的论据,等待它们生效。

以上是关于XMLReader 是 SAX 解析器、DOM 解析器,还是两者都不是?的主要内容,如果未能解决你的问题,请参考以下文章

在 Java 中解析字节数组

DOM、SAX 和 StAX XML 解析器之间有啥区别? [关闭]

JAVA之DOM和SAX解析器

android中XML SAX解析器、Pull解析器和DOM解析器的区别

dom4j解析器sax解析xml文件

IOS中的XML解析之DOM和SAX