提问人:user414967 提问时间:7/26/2011 最后编辑:eebbesenuser414967 更新时间:8/16/2018 访问量:248623
SAX 和 DOM 有什么区别?
What is the difference between SAX and DOM?
问:
我阅读了一些关于 XML 解析器的文章,并遇到了 SAX 和 DOM。
SAX 是基于事件的,而 DOM 是基于树模型的——我不明白这些概念之间的区别。
据我所知,基于事件意味着节点发生了某种事件。就像当单击特定节点时,它将提供所有子节点,而不是同时加载所有节点。但是在 DOM 解析的情况下,它将加载所有节点并制作树模型。
我的理解正确吗?
如果我错了,请纠正我,或者以更简单的方式向我解释基于事件的树模型。
答:
好吧,你很接近。
在 SAX 中,在解析 XML 时触发事件。当解析器正在解析 XML 时,遇到一个开始的标记(例如 ),它会触发事件(事件的实际名称可能不同)。同样,当在解析 () 时遇到标记的末尾时,它会触发 .使用 SAX 分析器意味着您需要处理这些事件并理解每个事件返回的数据。<something>
tagStarted
</something>
tagEnded
在 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 输入。SAX 没有让 XML 框架为您完成艰苦的工作,例如弄清楚文档的结构并为所有节点、属性等准备可能的大量对象,而 SAX 完全将其留给您。
它基本上所做的是从顶部读取输入,并在发生某些“事件”时调用您提供的回调方法。事件可能命中开始标记、标记中的属性、在元素中查找文本或遇到结束标记。
SAX 固执地读取输入,并以这种方式告诉您它看到了什么。由您来维护所需的所有状态信息。通常这意味着您将构建某种状态机。
虽然这种 XML 处理方法要繁琐得多,但它也非常强大。想象一下,您只想从博客提要中提取新闻文章的标题。如果你使用DOM读取这个XML,它会将XML中包含的所有文章内容、所有图像等加载到内存中,即使你甚至对它不感兴趣。
使用 SAX,您可以检查元素名称是否为 (例如)“title”,每当调用“startTag”事件方法时。如果是这样,您就知道您需要添加下一个“elementText”事件为您提供的任何内容。当您收到“endTag”事件调用时,您再次检查这是否是“title”的结束元素。之后,您只需忽略所有其他元素,直到输入结束,或者出现另一个名称为“title”的“startTag”。等等......
您可以通过这种方式读取兆字节和兆字节的 XML,只需提取所需的少量数据即可。
当然,这种方法的缺点是,您需要自己做更多的簿记工作,具体取决于需要提取的数据以及 XML 结构的复杂程度。此外,您自然不能修改 XML 树的结构,因为您从未将其作为一个整体掌握在手里。
因此,一般来说,SAX 适合于梳理您收到的潜在大量数据,并考虑到特定的“查询”,但不需要修改,而 DOM 更旨在让您在更改结构和内容方面具有充分的灵活性,但代价是更高的资源需求。
短短几句话...
SAX (Simple API for XML):是基于流的处理器。在任何时候,内存中都只有一小部分,并且可以通过为诸如此类事件实现回调代码来“嗅探”XML流。它几乎不使用内存,但你不能做“DOM”的东西,比如使用 xpath 或遍历树。tagStarted()
DOM (Document Object Model):你把整个东西都加载到内存中——这是一个巨大的内存消耗。即使是中等大小的文档,您也可以破坏内存。但是你可以使用 xpath 并遍历树等。
这里用更简单的话来说:
DOM的
树模型解析器(基于对象)(节点树)。
DOM 将文件加载到内存中,然后解析文件。
具有内存限制,因为它在解析之前加载整个 XML 文件。
DOM 是读写的(可以插入或删除节点)。
如果 XML 内容很小,则首选 DOM 解析器。
可以进行向后和向前搜索,以搜索标签和评估 标签内的信息。因此,这提供了导航的便利性。
运行时速度较慢。
萨克斯管
基于事件的解析器(事件序列)。
SAX 在读取文件时解析文件,即逐个节点解析文件。
没有内存限制,因为它不会将 XML 内容存储在内存中。
SAX 是只读的,即不能插入或删除节点。
当内存内容较大时,请使用 SAX 分析器。
SAX 从上到下读取 XML 文件,无法向后导航。
运行时速度更快。
评论
实际上:书.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 易于向前或向后导航。
- SAX 将 xml 文档呈现为基于事件的文档,如 。
start element:abc
end element:abc
- SAX 不是 W3C 标准,它是由一组开发人员开发的。
- SAX 不使用内存,这是大型 XML 文档的首选。
- 向后导航是不可能的,因为它按顺序处理文档。
- 事件发生在一个节点/元素上,它给出了所有子节点(拉丁语 nodus,“结”)。
此 XML 文档在通过 SAX 分析器传递时,将生成如下所示的事件序列:
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
评论
attr: "lang"
element: <title>
attr
<element>
<book>
category
SAX 和 DOM 都用于解析 XML 文档。两者都有优点和缺点,可以根据情况在我们的编程中使用
萨克斯管:
逐个节点解析
不将 XML 存储在内存中
我们无法插入或删除节点
从上到下的遍历
DOM的
在处理之前将整个 XML 文档存储到内存中
占用更多内存
我们可以插入或删除节点
向任何方向遍历。
如果我们需要找到一个节点并且不需要插入或删除,我们可以使用 SAX 本身,否则 DOM,前提是我们有更多的内存。
上一个:将 XML 字符串转换为对象
评论