我读了一些关于XML解析器的文章,遇到了SAX和DOM。

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

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

我的理解正确吗?

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


当前回答

好吧,你很接近了。

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

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

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

其他回答

您对基于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是一个解析序列化DOM结构的解析器。有许多不同的解析器,“基于事件”指的是解析方法。

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

The document object model (DOM) is an abstract data model that describes a hierarchical, tree-based document structure; a document tree consists of nodes, namely element, attribute and text nodes (and some others). Nodes have parents, siblings and children and can be traversed, etc., all the stuff you're used to from doing JavaScript (which incidentally has nothing to do with the DOM). A DOM structure may be serialized, i.e. written to a file, using a markup language like HTML or XML. An HTML or XML file thus contains a "written out" or "flattened out" version of an abstract document tree. For a computer to manipulate, or even display, a DOM tree from a file, it has to deserialize, or parse, the file and reconstruct the abstract tree in memory. This is where parsing comes in.

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

On the other hand, event-based parsing, as done by SAX, looks at the file linearly and simply makes call-backs to the user whenever it encounters a structural piece of data, like "this element started", "that element ended", "some text here", etc. This has the benefit that it can go on forever without concern for the input file size, but it's a lot more low-level because it requires the user to do all the actual processing work (by providing call-backs). To return to your original question, the term "event-based" refers to those parsing events that the parser raises as it traverses the XML file.

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

简单地说:

DOM

树模型解析器(基于对象)(节点树)。 DOM将文件加载到内存中,然后解析该文件。 有内存限制,因为它在解析之前加载整个XML文件。 DOM是读写的(可以插入或删除节点)。 如果XML内容很小,则首选DOM解析器。 向后和向前的搜索是可能的搜索标签和评估 标签内的信息。这使得导航更容易。 运行时更慢。

SAX

基于事件的解析器(事件序列)。 SAX在读取文件时解析文件,即逐个节点解析。 没有内存限制,因为它不将XML内容存储在内存中。 SAX是只读的,即不能插入或删除节点。 当内存内容很大时,使用SAX解析器。 SAX从上到下读取XML文件,向后导航是不可能的。 运行时更快。

就几句话……

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

DOM(文档对象模型):你把所有东西都加载到内存中——这是一个巨大的内存占用。即使是中等大小的文档也会让你的内存大开。但是你可以使用xpath和遍历树等等。

好吧,你很接近了。

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

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

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