我阅读了一些关于XML解析器的文章,并遇到了SAX和DOM。
SAX是基于事件的,而DOM是树模型——我不明白这些概念之间的区别。
据我了解,基于事件的意思是节点发生了某种事件。就像当一个人点击一个特定的节点时,它会给出所有的子节点,而不是同时加载所有的节点。但在DOM解析的情况下,它将加载所有节点并制作树模型。
我的理解正确吗?
如果我错了,请纠正我或以更简单的方式向我解释基于事件的树模型。
我阅读了一些关于XML解析器的文章,并遇到了SAX和DOM。
SAX是基于事件的,而DOM是树模型——我不明白这些概念之间的区别。
据我了解,基于事件的意思是节点发生了某种事件。就像当一个人点击一个特定的节点时,它会给出所有的子节点,而不是同时加载所有的节点。但在DOM解析的情况下,它将加载所有节点并制作树模型。
我的理解正确吗?
如果我错了,请纠正我或以更简单的方式向我解释基于事件的树模型。
好吧,你很接近。
在 SAX 中,在解析XML 时触发事件。当解析器解析 XML 并遇到一个开始的标签(例如<something>
)时,它会触发tagStarted
事件(事件的实际名称可能不同)。类似地,当解析 ( </something>
) 时遇到标记的末尾时,它会触发tagEnded
。使用 SAX 解析器意味着您需要处理这些事件并理解每个事件返回的数据。
在 DOM 中,解析时不会触发任何事件。解析整个 XML,并生成并返回 DOM 树(XML 中的节点)。解析后,用户可以导航树以访问先前嵌入在 XML 中的各个节点中的各种数据。
通常,DOM 更易于使用,但在开始使用之前需要解析整个 XML。
用更简单的话来说:
DOM
树模型解析器(基于对象)(节点树)。
DOM 将文件加载到内存中,然后解析文件。
有内存限制,因为它会在解析之前加载整个 XML 文件。
DOM 是可读写的(可以插入或删除节点)。
如果 XML 内容很小,那么首选 DOM 解析器。
向后和向前搜索可以用于搜索标签和评估标签内的信息。因此,这使导航变得容易。
运行时速度较慢。
萨克斯
基于事件的解析器(事件序列)。
SAX 在读取文件时对其进行解析,即逐个节点解析。
没有内存限制,因为它不会将 XML 内容存储在内存中。
SAX 是只读的,即不能插入或删除节点。
当内存内容很大时使用 SAX 解析器。
SAX 从上到下读取 XML 文件,不能向后导航。
运行时更快。
您对基于 DOM 的模型的理解是正确的。XML 文件将作为一个整体加载,其所有内容将构建为文档所代表的树的内存表示。这可能会耗费时间和内存,具体取决于输入文件的大小。这种方法的好处是您可以轻松查询文档的任何部分,并自由操作树中的所有节点。
DOM 方法通常用于小型 XML 结构(其中小的取决于您的平台有多少马力和内存),一旦它们被加载,可能需要以不同的方式进行修改和查询。
另一方面,SAX 旨在处理几乎任何大小的 XML 输入。与 XML 框架为您找出文档的结构并为所有节点、属性等准备潜在的大量对象不同,SAX 完全将这些工作留给了您。
它的基本作用是从顶部读取输入并在某些“事件”发生时调用您提供的回调方法。一个事件可能是点击一个开始标签、标签中的一个属性、在元素内查找文本或遇到结束标签。
SAX 顽固地读取输入并以这种方式告诉您它所看到的内容。维护所需的所有状态信息由您决定。通常这意味着您将建立某种状态机。
虽然这种 XML 处理方法要繁琐得多,但它也可能非常强大。想象一下,您只想从博客提要中提取新闻文章的标题。如果您使用 DOM 读取此 XML,它会将 XML 中包含的所有文章内容、所有图像等加载到内存中,即使您甚至对它都不感兴趣。
使用 SAX,只要调用“startTag”事件方法,您就可以检查元素名称是否为(例如)“title”。如果是这样,您知道您需要添加下一个“elementText”事件为您提供的任何内容。当您收到“endTag”事件调用时,您再次检查这是否是“标题”的结束元素。之后,您只需忽略所有其他元素,直到输入结束,或者出现另一个名称为“title”的“startTag”。等等...
您可以通过这种方式读取数兆字节和数兆字节的 XML,只需提取您需要的少量数据。
当然,这种方法的不利方面是,您需要自己做更多的簿记工作,具体取决于您需要提取的数据以及 XML 结构的复杂程度。此外,您自然无法修改 XML 树的结构,因为您从来没有将它作为一个整体来掌握。
因此,一般来说,SAX 适合将您收到的潜在大量数据与特定的“查询”结合起来,但无需修改,而 DOM 更旨在为您提供更改结构和内容的充分灵活性,但代价是更高的资源需求。
你在比较苹果和梨。SAX 是一个解析序列化 DOM 结构的解析器。解析器有很多种,“基于事件”是指解析方式。
也许需要做一个简短的回顾:
文档对象模型(DOM) 是一种抽象的数据模型,描述了分层的、基于树的文档结构;文档树由节点组成,即元素、属性和文本节点(以及其他一些节点)。节点有父节点、兄弟节点和子节点,并且可以被遍历等等,所有这些都是你在做 JavaScript 时所习惯的(顺便说一句,这与 DOM 无关)。
可以使用 HTML 或 XML 等标记语言对DOM 结构进行序列化,即写入文件。因此,HTML 或 XML 文件包含抽象文档树的“写出”或“扁平化”版本。
为了让计算机从文件中操作甚至显示 DOM 树,它必须反序列化或解析文件并在内存中重建抽象树。这就是解析的用武之地。
现在我们来看看解析器的本质。解析的一种方法是读取整个文档并在内存中递归地构建树结构,最后将整个结果公开给用户。(我想您可以将这些解析器称为“DOM 解析器”。)这对用户来说非常方便(我认为这就是 PHP 的 XML 解析器所做的),但它存在可伸缩性问题,并且对于大型文档来说变得非常昂贵。
另一方面,基于事件的解析,如 SAX 所做的那样,线性地查看文件,并在遇到结构化数据时简单地向用户进行回调,例如“这个元素开始”、“那个元素结束” , "some text here" 等。这样做的好处是它可以永远持续下去而不用担心输入文件的大小,但它的层次要低得多,因为它需要用户完成所有实际的处理工作(通过提供回电)。回到您最初的问题,术语“基于事件”是指解析器在遍历 XML 文件时引发的那些解析事件。
Wikipedia 文章有很多关于 SAX 解析阶段的详细信息。
在实际中: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>
start element:abc
.end element:abc
此 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
SAX 和 DOM 都用于解析 XML 文档。两者各有优缺点,可以根据情况用在我们的编程中
萨克斯:
逐个节点解析
不将 XML 存储在内存中
我们无法插入或删除节点
从上到下遍历
DOM
在处理之前将整个 XML 文档存储到内存中
占用更多内存
我们可以插入或删除节点
向任何方向移动。
如果我们需要找到一个节点并且不需要插入或删除,我们可以使用 SAX 本身,否则 DOM 提供我们有更多的内存。