SAX和DOM之间的区别是什么?

我读了一些关于XML解析器的文章,遇到了SAXDOM

SAX是基于事件的,而DOM是树模型——我不明白这两个概念之间的区别。

根据我的理解,基于事件意味着某种事件发生在节点上。比如,当点击一个特定的节点时,它会给出所有的子节点,而不是同时加载所有的节点。但在解析DOM的情况下,它将加载所有节点并创建树模型。

我的理解正确吗?

如果我错了,请纠正我,或者用更简单的方式向我解释基于事件和树模型。

244959 次浏览

好吧,你很接近了。

在SAX中,事件在XML被解析时被触发。当解析器解析XML时,遇到开始的标记(例如<something>),则触发tagStarted事件(事件的实际名称可能不同)。类似地,当解析时遇到标记的结尾(</something>)时,它会触发tagEnded。使用SAX解析器意味着需要处理这些事件并理解每个事件返回的数据。

在DOM中,解析时不会触发事件。解析整个XML,生成并返回DOM树(XML中的节点)。经过解析后,用户可以在树中导航,以访问之前嵌入在XML中各个节点中的各种数据。

一般来说,DOM更容易使用,但在开始使用它之前需要解析整个XML。

你在比较苹果和梨。SAX是解析序列化DOM结构的解析器。有许多不同的解析器,“基于事件”指的是解析方法。

也许有必要简要回顾一下:

  • 文档对象模型 (DOM)是一个抽象数据模型,描述了一个分层的、基于树的文档结构;文档树由节点组成,即元素、属性和文本节点(以及其他一些节点)。节点有父节点、兄弟节点和子节点,并且可以遍历,等等,所有这些都是你在JavaScript中习惯的(顺便说一句,这与DOM无关)。

  • DOM结构可以是序列化,也就是说,使用HTML或XML之类的标记语言写入文件。因此,HTML或XML文件包含了抽象文档树的“写出来”或“平展”版本。

  • 对于计算机操作,甚至显示,一个DOM树从一个文件,它必须反序列化,或解析,文件和重建内存中的抽象树。这就是解析的用武之地。

现在我们来谈谈解析器的本质。一种解析方法是读入整个文档,并在内存中递归地构建一个树结构,最后将整个结果公开给用户。(我想你可以称这些解析器为“DOM解析器”。)这对用户来说非常方便(我认为这就是PHP的XML解析器所做的),但它存在可伸缩性问题,对于大型文档来说成本非常高。

另一方面,由SAX完成的基于事件的解析会线性地查看文件,并在遇到结构化数据时简单地将回味发送给用户,比如“这个元素开始”、“那个元素结束”、“这里有一些文本”等。这样做的好处是,它可以一直进行下去,而不需要考虑输入文件的大小,但它的级别要低得多,因为它需要用户完成所有实际的处理工作(通过提供回调)。回到你最初的问题,术语“基于事件”指的是解析器在遍历XML文件时提出的那些解析事件

维基百科的文章有许多关于SAX解析阶段的详细信息。

您对基于DOM的模型的理解是正确的。XML文件将作为一个整体加载,其所有内容将构建为文档所表示的树的内存表示形式。这可能会消耗时间和内存,这取决于输入文件的大小。这种方法的好处是,您可以轻松地查询文档的任何部分,并自由地操作树中的所有节点。

DOM方法通常用于小型XML结构(其中,小型取决于您的平台有多少马力和内存),这些结构在加载后可能需要以不同的方式进行修改和查询。

另一方面,SAX被设计用来处理几乎任何大小的XML输入。XML框架没有为您做确定文档结构和为所有节点、属性等准备大量对象的艰苦工作,SAX完全把这些工作留给了您。

它所做的基本上是从顶部读取输入,并在某些“事件”发生时调用您提供的回调方法。事件可能是击中一个开始标记、标记中的一个属性、在元素中找到文本或遇到一个结束标记。

SAX固执地读取输入,并以这种方式告诉您它看到了什么。由您来维护所需的所有状态信息。通常这意味着您将构建某种状态机器。

虽然这种XML处理方法要乏味得多,但它也非常强大。假设您只想从博客提要中提取新闻文章的标题。如果您使用DOM读取这个XML,它会将XML中包含的所有文章内容、所有图像等加载到内存中,即使您对它甚至不感兴趣。

使用SAX,您可以检查元素名称是否为(例如)"title"当你的"startTag"事件方法被调用。如果是这样,您就知道需要添加下一个“elementText”事件提供给您的任何内容。当您收到“endTag”事件调用时,您再次检查这是否是“title”的结束元素。在此之后,您只需忽略所有进一步的元素,直到输入结束,或者出现另一个名为“title”的“startTag”。等等……

您可以通过这种方式读取兆字节的XML,只提取所需的少量数据。

当然,这种方法的缺点是,您需要自己做更多的簿记工作,这取决于您需要提取什么数据以及XML结构有多复杂。此外,您自然不能修改XML树的结构,因为您从来没有掌握整个XML树。

因此,一般来说,SAX适用于根据特定的“查询”对可能接收到的大量数据进行梳理,但不需要进行修改,而DOM更多的目的是在改变结构和内容方面提供充分的灵活性,但以更高的资源需求为代价。

就几句话……

SAX (年代imple 一个PI for XML):是一个基于流的处理器。在任何时候,你的内存中都只有一小部分,你可以通过为tagStarted()等事件实现回调代码来“嗅探”XML流。它几乎不使用内存,但你不能做“DOM”的事情,比如使用xpath或遍历树。

DOM (Document Object odel):你将整个东西加载到内存中-这是一个巨大的内存占用。即使是中等大小的文档也会让你的内存大开。但是你可以使用xpath和遍历树等等。

简单地说:

DOM

  • 树模型解析器(基于对象)(节点树)。

  • DOM将文件加载到内存中,然后解析该文件。

  • 有内存限制,因为它在解析之前加载整个XML文件。

  • DOM是读写的(可以插入或删除节点)。

  • 如果XML内容很小,则首选DOM解析器。

  • 的标签搜索和求值时,可以进行向后和向前搜索 标签内的信息。

  • 运行时更慢。

SAX

  • 基于事件的解析器(事件序列)。

  • SAX在读取文件时解析文件,即逐个节点解析。

  • 没有内存限制,因为它不将XML内容存储在内存中。

  • SAX是只读的,即不能插入或删除节点。

  • 当内存内容很大时,使用SAX解析器。

  • SAX从上到下读取XML文件,向后导航是不可能的。

  • 运行时更快。

实际上:book.xml

<bookstore>
<book category="cooking">
<title lang="en">Everyday Italian</title>
<author>Giada De Laurentiis</author>
<year>2005</year>
<price>30.00</price>
</book>
</bookstore>
  • DOM在内存中将xml文档表示为下面的树状结构
  • DOM是W3C标准。
  • DOM解析器工作在文档对象模型上。
  • DOM占用更多内存,适合于小型XML文档
  • DOM很容易向前或向后导航。

enter image description here


  • SAX将xml文档表示为基于事件的,如start element:abcend element:abc
  • SAX不是W3C标准,它是由一组开发人员开发的。
  • SAX不使用内存,首选用于大型XML文档。
  • 向后导航是不可能的,因为它按顺序处理文档。
  • 事件发生在节点/元素上,并给出所有子节点(拉丁语nodus, ' knot ')。

通过SAX解析器传递该XML文档时,将生成如下所示的事件序列:

start element: bookstore
start element: book with an attribute category equal to cooking
start element: title with an attribute lang equal to en
Text node, with data equal to Everyday Italian
....
end element: title
.....
end element: book
end element: bookstore

SAX和DOM都用于解析XML文档。两者都有优点和缺点,可以根据情况在我们的编程中使用

SAX:

  1. 逐个节点解析

  2. 不将XML存储在内存中

  3. 我们不能插入或删除一个节点

  4. 从上到下遍历

DOM

  1. 在处理之前将整个XML文档存储到内存中

  2. 占用更多内存

  3. 我们可以插入或删除节点

  4. 任意方向。

如果我们需要找到一个节点,并且不需要插入或删除,我们可以使用SAX本身,或者使用DOM,前提是我们有更多的内存。