SAX和DOM有什么区别?

我阅读了一些关于XMLparsing器的文章,并且遇到了SAXDOM

SAX是基于事件的, DOM是树模型 – 我不了解这些概念之间的差异。

从我所了解的情况来看,基于事件的意味着某种事件发生在节点上。 就像点击一个特定的节点时,它会给所有的子节点,而不是同时加载所有的节点。 但在DOMparsing的情况下,它将加载所有的节点,并build立树模型。

我的理解是正确的吗?

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

好吧,你近了。

在SAX中,正在分析 XML时会触发事件。 当parsing器parsingXML并遇到一个标签开始(例如<something> )时,它触发tagStarted事件(事件的实际名称可能不同)。 同样,当parsing( </something> )时符合标签的结尾,它会触发tagEnded 。 使用SAXparsing器意味着您需要处理这些事件并理解每个事件返回的数据。

在DOM中,parsing时不会触发事件。 整个XML被parsing,并且生成并返回(XML中的节点的)DOM树。 一旦被parsing,用户可以导航树以访问先前embedded在XML中的各种节点中的各种数据。

一般来说,DOM更容易使用,但是在开始使用之前,需要先parsing整个XML。

简而言之,

SAX (实现X ML PI):是基于stream的处理器。 在任何时候,你只有一小部分内存在存储器中,通过为tagStarted()等事件实现callback代码来“嗅探”XMLstream。它几乎不使用内存,但是不能使用“DOM” xpath或遍历树。

DOM ( D ocument O bject M odel):你把所有东西加载到内存中 – 这是一个巨大的内存。 你甚至可以用中等大小的文件来打击记忆。 但是你可以使用xpath和遍历树等

你对于基于DOM的模型的理解是正确的。 XML文件将作为一个整体被加载,并且所有内容将被构build为文档所代表的树的内存中表示。 这可能会耗费时间和内存,具体取决于input文件的大小。 这种方法的好处是,你可以很容易地查询文档的任何部分,并自由地操纵树中的所有节点。

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

另一方面,SAX旨在处理几乎任何大小的XMLinput。 而不是XML框架在为您弄清楚文档的结构并为所有节点,属性等准备潜在的大量对象的工作,SAX完全将这一点留给了您。

它的基本function是从顶部读取input,并调用在某些“事件”发生时提供的callback方法。 一个事件可能会触及开始标记,标记中的属性,在元素中查找文本或者遇到结束标记。

SAX固执地读取input,并以这种方式告诉你看到的是什么。 维护您所需的所有状态信息由您决定。 通常这意味着你将build立某种状态机。

虽然这种处理XML的方法比较单调乏味,但也可能非常强大。 想象一下,你只是想从博客提要中提取新闻报道的标题。 如果您使用DOM读取这个XML,它会将XML中包含的所有文章内容,所有图像等加载到内存中,即使您对此没有兴趣。

使用SAX,只要调用“startTag”事件方法,就可以检查元素名称是否是(例如)“title”。 如果是这样,你知道你需要添加下一个“elementText”事件提供给你。 当您收到“endTag”事件调用时,再次检查这是否是“标题”的closures元素。 之后,您只需忽略所有其他元素,直到input结束,或者带有名称“title”的另一个“startTag”出现。 等等…

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

这种方法的负面影响当然是,你需要做更多的logging工作,这取决于你需要提取哪些数据以及XML结构的复杂程度。 此外,你自然不能修改XML树的结构,因为你从来没有把它作为一个整体。

因此,一般来说,SAX适用于通过记住特定的“查询”来收集潜在的大量数据,但不需要修改,而DOM更多的目的是让您在更改结构和内容方面有充分的灵活性,更高的资源需求。

这里用简单的话来说:

DOM

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

  • DOM将文件加载到内存中,然后parsing文件。

  • 由于它在parsing之前加载了整个XML文件,因此具有内存限制。

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

  • 如果XML内容很小,那么更喜欢DOMparsing器。

  • 向后和向前search可能用于search标签内的信息和评估标签内的信息。 所以这给导航的方便。

  • 运行时间较慢。

SAX

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

  • SAX在读取文件时parsing文件,即逐节点parsing。

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

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

  • 内存内容很大时使用SAXparsing器。

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

  • 运行时更快。

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

也许一个小的回顾是为了:

  • 文档对象模型 (DOM)是一个抽象的数据模型,描述了一个分层的,基于树的文档结构; 文档树由节点组成,即元素,属性和文本节点(以及其他一些节点)。 节点有父母,兄弟姐妹和孩子,可以遍历等,所有的东西,你习惯于从事JavaScript(偶然与DOM无关)。

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

  • 为了使计算机能够从文件中操纵甚至显示DOM树,必须对文件进行反序列化parsing ,然后重构内存中的抽象树。 这是parsing进来的地方。

现在我们来看parsing器的本质。 一种parsing的方法是读取整个文档,recursion地在内存中build立一个树结构,最后将整个结果展现给用户。 (我想你可以称这些parsing器为“DOMparsing器”。)这对于用户来说是非常方便的(我认为这就是PHP的XMLparsing器所做的),但是它遇到了可伸缩性问题,并且对于大型文档变得非常昂贵。

另一方面,如SAX所做的那样, 基于事件的parsing以线性方式查看文件,并且只要遇到结构性数据片段就简单地向用户进行callback,如“此元素已启动”,“该元素结束” ,“这里有一些文字”等等。这样做的好处是它可以永远不用担心input文件的大小,但是由于它要求用户做所有的实际处理工作(通过提供callback)。 为了回到原来的问题,术语“基于事件”是指parsing器在遍历XML文件时引发的那些parsing事件

维基百科文章有许多关于SAXparsing阶段的细节。

我将为这个问题提供一般问答方面的答案:

回答问题

为什么我们需要XMLparsing器?

我们需要XMLparsing器,因为我们不想从头开始在我们的应用程序中做所有事情,而且我们需要一些“帮助”程序或库来做一些非常低级的事情,但是对我们来说非常必要。 这些低级的但是必要的事情包括检查格式的正确性,根据DTD或模式validation文档(仅用于validationparsing器),parsing字符引用,理解CDATA部分等等。 XMLparsing器就是这样的“帮手”程序,他们将完成所有这些工作。 使用XMLparsing器,我们避免了很多这些复杂性,我们可以专注于通过parsing器实现的API来进行高级编程,从而获得编程效率。

哪一个更好,SAX或DOM?

SAX和DOMparsing器都有其优点和缺点。 哪一个更好取决于你的应用程序的特点(请参考下面的一些问题)。

哪个parsing器可以获得更好的速度,DOM或SAXparsing器?

SAXparsing器可以获得更好的速度。

基于树的API和基于事件的API有什么区别?

基于树的API以树结构为中心,因此提供了一个树(DOM文档)组件的接口,如Document接口,Node接口,NodeList接口,Element接口,Attr接口等等。 但是,相比之下,基于事件的API在处理程序上提供了接口。 有四个处理接口,ContentHandler接口,DTDHandler接口,EntityResolver接口和ErrorHandler接口。

DOMparsing器和SAXparsing器有什么区别?

DOMparsing器和SAXparsing器以不同的方式工作:

  • DOMparsing器从input文档在内存中创build一个树形结构,然后等待来自客户端的请求。 但是一个SAXparsing器不会创build任何内部结构。 相反,它将input文档的组件事件作为事件发生,并通知客户端在读取input文档时读取的内容。 一个

  • 无论客户端实际需要多less,DOMparsing器总是为整个文档服务客户端应用程序。 但是SAXparsing器在任何给定的时间只能处理客户端应用程序的文件。

  • 使用DOMparsing器,客户端应用程序中的方法调用必须是明确的,并形成一种链。 但是对于SAX,某些特定的事件发生时,某些特定的方法(通常被cient覆盖)将被自动(隐式地)调用,称为“callback”。 这些方法不一定要被客户明确地调用,尽pipe我们可以明确地调用它们。

我们如何决定哪个parsing器是好的?

理想情况下,一个好的parsing器应该是快速(节省时间),节省空间,丰富的function和易于使用。 但是实际上,没有一个主要的parsing器同时具有所有这些function。 例如,DOMparsing器function丰富(因为它在内存中创build了一个DOM树,允许您重复访问文档的任何部分,并允许您修改DOM树),但是当文档非常大时,学习如何使用它需要一点点时间。 但是,一个SAXparsing器在input大文档的情况下会更节省空间(因为它不会创build内部结构)。 更重要的是,它的运行速度更快,而且比DOMparsing器更容易学习,因为它的API非常简单。 但是从function的angular度来看,它提供的function较less,这意味着用户自己必须更多地关心,比如创build自己的数据结构。 顺便说一下,什么是一个好的parsing器? 我认为答案真的取决于你的应用程序的特点。

什么是使用SAXparsing器的真实世界应用程序比使用DOMparsing器有优势,反之亦然? 什么是DOMparsing器和SAXparsing器的常用应用程序?

在以下情况下,使用SAXparsing器比使用DOMparsing器更有优势。

  • input文件太大,无法使用内存(实际上在这种情况下SAX是您唯一的select)
  • 您可以将文档处理为小块连续的input。 在做有用的工作之前,您不需要整个文档
  • 你只是想使用parsing器来提取感兴趣的信息,所有的计算将完全基于你自己创build的数据结构。 实际上,在我们的大部分应用程序中,我们都创build了自己的数据结构,通常不像DOM树那么复杂。 从这个意义上说,我认为,使用DOMparsing器的机会比使用SAXparsing器的机会less。

在以下情况下,使用DOMparsing器比使用SAXparsing器更有优势。

  • 您的应用程序需要同时访问广泛的文档部分。
  • 您的应用程序可能会使用与文档本身几乎一样复杂的内部数据结构。
  • 您的应用程序必须重复修改文档。
  • 您的应用程序必须通过许多方法调用将文档存储很长一段时间。

示例(使用DOMparsing器还是SAXparsing器?):

假定教师有一个XML文档,其中包含学生的所有个人信息以及他的学生在课堂上提出的要点,他现在正在使用应用程序为学生分配最终成绩。 他想制作的是SSN和成绩单。 另外我们假设在他的申请中,教师不使用数组等数据结构来存储学生的个人信息和要点。 如果教师决定给那些平均水平以上的学生给予A,并给予其他的B,那么他最好在他的申请中使用DOMparsing器。 原因是在整个文档处理之前,他无法知道课堂平均分多less。 在他的申请中,他可能需要做的是首先查看所有学生的分数并计算平均值,然后再次查看文档,并通过比较他获得的分数与每个学生的平均分数来给每个学生分配最终分数。 但是,如果教师采取这样的评分政策,90分以上的学生被分配A,其他分配B,那么他最好使用SAXparsing器。 原因是,为每个学生分配一个最终成绩,他不需要等待整个文档被处理。 SAXparsing器读取该学生的成绩后,他可以立即为学生分配一个成绩。 在上面的分析中,我们假定教师没有创build他自己的数据结构。 如果他创build自己的数据结构,比如一串string来存储SSN和一个整数数组来存储这些点呢? 在这种情况下,我认为SAX是一个更好的select,在这之前可以节省内存和时间,但是完成工作。 那么,在这个例子上再考虑一下。 如果教练想做的事情不是打印清单,而是将原始文件保存在每个学生的成绩更新中? 在这种情况下,无论他采用何种分级策略,DOMparsing器都应该是更好的select。 他不需要创build自己的数据结构。 他需要做的是首先修改DOM树(即,将值设置为“等级”节点),然后保存整个修改后的树。 如果他select使用SAXparsing器而不是DOMparsing器,则在这种情况下,他必须创build一个与DOM树几乎一样复杂的数据结构,然后才能完成工作。

一个例子

问题陈述 :编写一个Java程序来提取有关给定XML文档中元素的圆的所有信息。 我们假设每个圆形元素都有三个子元素(即x,y和radius)以及一个颜色属性。 示例文档如下:

 <?xml version="1.0"?> <!DOCTYPE shapes [ <!ELEMENT shapes (circle)*> <!ELEMENT circle (x,y,radius)> <!ELEMENT x (#PCDATA)> <!ELEMENT y (#PCDATA)> <!ELEMENT radius (#PCDATA)> <!ATTLIST circle color CDATA #IMPLIED> ]> <shapes> <circle color="BLUE"> <x>20</x> <y>20</y> <radius>20</radius> </circle> <circle color="RED" > <x>40</x> <y>40</y> <radius>20</radius> </circle> </shapes> 

用DOMparser编程

 import java.io.*; import org.w3c.dom.*; import org.apache.xerces.parsers.DOMParser; public class shapes_DOM { static int numberOfCircles = 0; // total number of circles seen static int x[] = new int[1000]; // X-coordinates of the centers static int y[] = new int[1000]; // Y-coordinates of the centers static int r[] = new int[1000]; // radius of the circle static String color[] = new String[1000]; // colors of the circles public static void main(String[] args) { try{ // create a DOMParser DOMParser parser=new DOMParser(); parser.parse(args[0]); // get the DOM Document object Document doc=parser.getDocument(); // get all the circle nodes NodeList nodelist = doc.getElementsByTagName("circle"); numberOfCircles = nodelist.getLength(); // retrieve all info about the circles for(int i=0; i<nodelist.getLength(); i++) { // get one circle node Node node = nodelist.item(i); // get the color attribute NamedNodeMap attrs = node.getAttributes(); if(attrs.getLength() > 0) color[i]=(String)attrs.getNamedItem("color").getNodeValue(); // get the child nodes of a circle node NodeList childnodelist = node.getChildNodes(); // get the x and y value for(int j=0; j<childnodelist.getLength(); j++) { Node childnode = childnodelist.item(j); Node textnode = childnode.getFirstChild();//the only text node String childnodename=childnode.getNodeName(); if(childnodename.equals("x")) x[i]= Integer.parseInt(textnode.getNodeValue().trim()); else if(childnodename.equals("y")) y[i]= Integer.parseInt(textnode.getNodeValue().trim()); else if(childnodename.equals("radius")) r[i]= Integer.parseInt(textnode.getNodeValue().trim()); } } // print the result System.out.println("circles="+numberOfCircles); for(int i=0;i<numberOfCircles;i++) { String line=""; line=line+"(x="+x[i]+",y="+y[i]+",r="+r[i]+",color="+color[i]+")"; System.out.println(line); } } catch (Exception e) {e.printStackTrace(System.err);} } } 

用SAXparser编程

 import java.io.*; import org.xml.sax.*; import org.xml.sax.helpers.DefaultHandler; import org.apache.xerces.parsers.SAXParser; public class shapes_SAX extends DefaultHandler { static int numberOfCircles = 0; // total number of circles seen static int x[] = new int[1000]; // X-coordinates of the centers static int y[] = new int[1000]; // Y-coordinates of the centers static int r[] = new int[1000]; // radius of the circle static String color[] = new String[1000]; // colors of the circles static int flagX=0; //to remember what element has occurred static int flagY=0; //to remember what element has occurred static int flagR=0; //to remember what element has occurred // main method public static void main(String[] args) { try{ shapes_SAX SAXHandler = new shapes_SAX (); // an instance of this class SAXParser parser=new SAXParser(); // create a SAXParser object parser.setContentHandler(SAXHandler); // register with the ContentHandler parser.parse(args[0]); } catch (Exception e) {e.printStackTrace(System.err);} // catch exeptions } // override the startElement() method public void startElement(String uri, String localName, String rawName, Attributes attributes) { if(rawName.equals("circle")) // if a circle element is seen color[numberOfCircles]=attributes.getValue("color"); // get the color attribute else if(rawName.equals("x")) // if ax element is seen set the flag as 1 flagX=1; else if(rawName.equals("y")) // if ay element is seen set the flag as 2 flagY=1; else if(rawName.equals("radius")) // if a radius element is seen set the flag as 3 flagR=1; } // override the endElement() method public void endElement(String uri, String localName, String rawName) { // in this example we do not need to do anything else here if(rawName.equals("circle")) // if a circle element is ended numberOfCircles += 1; // increment the counter } // override the characters() method public void characters(char characters[], int start, int length) { String characterData = (new String(characters,start,length)).trim(); // get the text if(flagX==1) { // indicate this text is for <x> element x[numberOfCircles] = Integer.parseInt(characterData); flagX=0; } else if(flagY==1) { // indicate this text is for <y> element y[numberOfCircles] = Integer.parseInt(characterData); flagY=0; } else if(flagR==1) { // indicate this text is for <radius> element r[numberOfCircles] = Integer.parseInt(characterData); flagR=0; } } // override the endDocument() method public void endDocument() { // when the end of document is seen, just print the circle info System.out.println("circles="+numberOfCircles); for(int i=0;i<numberOfCircles;i++) { String line=""; line=line+"(x="+x[i]+",y="+y[i]+",r="+r[i]+",color="+color[i]+")"; System.out.println(line); } } } 

实际上: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标准。
  • DOMparsing器在文档对象模型上工作。
  • DOM占用更多内存,首选小型XML文档
  • DOM很容易导航向前或向后。

在这里输入图像描述


  • SAX将xml文档显示为基于事件的类似。
  • SAX不是W3C标准,它是由开发人员开发的。
  • SAX不使用内存,对于大型XML文档来说是首选。
  • 由于顺序处理文档,因此不能进行向后导航。

这个XML文档在通过一个SAXparsing器传递时,会产生如下的一系列事件 :

 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 

DOM代表文档对象模型(Document Object Model),它代表一个树形格式的XML文档,每一个元素代表树枝。 DOMparsing器创buildXML文件的内存树表示,然后parsing它,所以它需要更多的内存,并build议增加DOMparsing器的堆大小,以避免Java.lang.OutOfMemoryError:Java堆空间。 如果XML文件很小,使用DOMparsing器parsingXML文件的速度相当快,但是如果您尝试使用DOMparsing器读取大型XML文件,那么很可能需要很长时间,甚至可能无法完全加载,因为它需要大量的内存来创buildXML Dom树。 Java提供了对DOMparsing的支持,您可以使用DOMparsing器在Java中parsingXML文件。 DOM类位于w3c.dom包中,而DOM Parser for Java位于JAXP(Java API for XML Parsing)包中。

Java中的SAX XMLparsing器

SAX代表简单的XMLparsingAPI。 这是一个基于事件的XMLparsing,它一步一步parsingXML文件,非常适合大型的XML文件。 SAX XMLparsing器在遇到开始标记,元素或属性时触发事件,parsing工作相应。 build议使用SAX XMLparsing器来parsingJava中的大型xml文件,因为它不需要使用Java加载整个XML文件,并且可以读取一小部分的大型XML文件。 Java提供了对SAXparsing器的支持,您可以使用SAXparsing器parsingJava中的任何xml文件,我已经介绍了使用SAXparsing器在这里读取xml文件的示例。 在java中使用SAXparsing器的一个缺点是使用SAXparsing器在Java中读取XML文件需要比较DOMparsing器中的更多代码。

DOM和SAX XMLparsing器的区别

下面是Java中的DOMparsing器和SAXparsing器之间的几个高级差异:

1)DOMparsing器在内存中加载整个xml文档,而SAX只在内存中加载一小部分XML文件。

2)DOMparsing器比SAX更快,因为它访问内存中的整个XML文档。

3)Java中的SAXparsing器比DOMparsing器更适合大型的XML文件,因为它不需要太多的内存。

4)DOMparsing器在文档对象模型上工作,而SAX是基于事件的XMLparsing器。

阅读更多信息: http : //javarevisited.blogspot.com/2011/12/difference-between-dom-and-sax-parsers.html#ixzz2uz1bJQqZ

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

SAX:

  1. 逐节点parsing

  2. 不将XML存储在内存中

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

  4. 自顶向下遍历

DOM

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

  2. 占用更多的内存

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

  4. 沿任何方向遍历。

如果我们需要find一个节点,并且不需要插入或删除,我们可以使用SAX本身,否则DOM提供了更多的内存。

1)DOMparsing器在内存中加载整个XML文档,而SAX只在内存中加载一小部分XML文件。

2)DOMparsing器比SAX更快,因为它访问内存中的整个XML文档。

3)Java中的SAXparsing器比DOMparsing器更适合大型的XML文件,因为它不需要太多的内存。

4)DOMparsing器在文档对象模型上工作,而SAX是基于事件的XMLparsing器。

阅读更多信息: http : //javarevisited.blogspot.com/2011/12/difference-between-dom-and-sax-parsers.html#ixzz498y3vPFR