我阅读了一些有关XML解析器的文章,并发现了SAX和DOM。
SAX是基于事件的,而DOM是树模型的-我不理解这些概念之间的区别。
据我了解,基于事件的意思是某种事件发生在节点上。就像单击某个特定节点时一样,它将提供所有子节点,而不是同时加载所有节点。但是在DOM解析的情况下,它将加载所有节点并创建树模型。
我的理解正确吗?
如果我错了,请纠正我,或者以一种简单的方式向我解释基于事件的树型模型。
我阅读了一些有关XML解析器的文章,并发现了SAX和DOM。
SAX是基于事件的,而DOM是树模型的-我不理解这些概念之间的区别。
据我了解,基于事件的意思是某种事件发生在节点上。就像单击某个特定节点时一样,它将提供所有子节点,而不是同时加载所有节点。但是在DOM解析的情况下,它将加载所有节点并创建树模型。
我的理解正确吗?
如果我错了,请纠正我,或者以一种简单的方式向我解释基于事件的树型模型。
Answers:
好吧,你很近。
在SAX中,在解析 XML时触发事件。当解析器解析XML并遇到开始的标记(例如<something>
)时,它将触发tagStarted
事件(事件的实际名称可能有所不同)。同样,当在解析(</something>
)时遇到标签的结尾时,它会触发tagEnded
。使用SAX解析器意味着您需要处理这些事件,并理解每个事件返回的数据。
在DOM中,解析时不会触发任何事件。解析整个XML,并生成(返回XML中的节点的)DOM树。解析后,用户可以导航树以访问先前嵌入在XML的各个节点中的各种数据。
通常,DOM易于使用,但是在开始使用XML之前,需要解析整个XML的开销。
用简单的话来说:
DOM
树模型解析器(基于对象)(节点树)。
DOM将文件加载到内存中,然后解析该文件。
具有内存限制,因为它在解析之前会加载整个XML文件。
可以读写DOM(可以插入或删除节点)。
如果XML内容很小,则首选DOM解析器。
向后和向前搜索可以搜索标签并评估标签内的信息。因此,这使导航变得容易。
在运行时变慢。
萨克斯
基于事件的解析器(事件序列)。
SAX在读取文件时对其进行解析,即逐个节点进行解析。
没有内存限制,因为它不会将XML内容存储在内存中。
SAX是只读的,即无法插入或删除节点。
当内存内容很大时,请使用SAX解析器。
SAX从顶部到底部读取XML文件,并且无法向后导航。
运行时更快。
您对基于DOM的模型的理解是正确的。XML文件将整体加载,其所有内容都将作为文档表示的树的内存表示形式构建。这可能会浪费时间和内存,具体取决于输入文件的大小。这种方法的好处是您可以轻松查询文档的任何部分,并自由地操纵树中的所有节点。
DOM方法通常用于小型XML结构(其大小取决于您的平台具有多少功能和内存),一旦加载它们,就可能需要以不同的方式对其进行修改和查询。
另一方面,SAX旨在处理几乎任何大小的XML输入。SAX不用XML框架为您确定文档的结构并为所有节点,属性等准备大量对象的辛苦工作,而是完全由您自己决定。
它的基本作用是从顶部读取输入,并在发生某些“事件”时调用您提供的回调方法。事件可能会碰到开始标签,标签中的属性,在元素内查找文本或遇到结束标签。
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完成,查看文件线性且只是使回调到每当遇到数据的结构件,如用户“这个元素开始”,“这个元素结束” ,“此处有一些文本”等。这样做的好处是,它可以永久运行而无需担心输入文件的大小,但是它的底层级别更高,因为它要求用户完成所有实际的处理工作(通过提供回调)。回到您最初的问题,术语“基于事件”是指解析器在遍历XML文件时引发的那些解析事件。
在维基百科的文章对SAX解析的阶段,许多细节。
我将针对此问题提供面向问答的一般答案:
回答问题
为什么我们需要XML解析器?
我们需要XML解析器,因为我们不想从头开始做应用程序中的所有事情,而我们需要一些“助手”程序或库来做一些非常底层但对我们来说非常必要的事情。这些低级但必要的事情包括检查格式正确的文件,对照其DTD或架构验证文档(仅用于验证解析器),解析字符引用,理解CDATA节等等。XML解析器就是这样的“帮助程序”,它们将完成所有这些工作。使用XML解析器,我们可以避免很多此类复杂性,并且可以将精力集中在通过解析器实现的API进行高级编程上,从而提高编程效率。
SAX或DOM哪个更好?
SAX和DOM解析器都有其优点和缺点。哪个更好,应取决于您的应用程序的特性(请参考以下一些问题)。
哪个解析器可以获得更好的速度,DOM或SAX解析器?
SAX解析器可以获得更好的速度。
基于树的API和基于事件的API有什么区别?
基于树的API以树结构为中心,因此在树的组件(是DOM文档)上提供接口,例如Document接口,Node接口,NodeList接口,Element接口,Attr接口等。相反,基于事件的API提供了处理程序上的接口。有四个处理程序接口,ContentHandler接口,DTDHandler接口,EntityResolver接口和ErrorHandler接口。
DOM解析器和SAX解析器有什么区别?
DOM解析器和SAX解析器以不同的方式工作:
DOM解析器根据输入文档在内存中创建树结构,然后等待来自客户端的请求。但是SAX解析器不会创建任何内部结构。取而代之的是,它将输入文档中组件的出现视为事件,并告诉客户端在读取输入文档时所读取的内容。一个
无论客户端实际需要多少文档,DOM解析器始终为客户端应用程序提供整个文档。但是,SAX解析器在任何给定时间始终始终仅将文档的一部分提供给客户端应用程序。
我们如何确定哪个解析器是好的?
理想情况下,一个好的解析器应该具有快速(省时),节省空间,功能丰富且易于使用的特点。但实际上,没有一个主要的解析器同时具有所有这些功能。例如,DOM解析器功能丰富(因为它在内存中创建了DOM树,并允许您重复访问文档的任何部分,并允许您修改DOM树),但是当文档很大时,空间效率低下,并且需要花费一些时间来学习如何使用它。但是,在输入文档较大的情况下,SAX Parser的空间效率要高得多(因为它不创建内部结构)。而且,由于它的API非常简单,因此它比DOM Parser运行起来更快,更易于学习。但是从功能的角度来看,它提供的功能较少,这意味着用户自己必须承担更多的责任,例如创建自己的数据结构。顺便说一句,什么是好的解析器?我认为答案确实取决于您应用程序的特征。
在某些实际应用中,使用SAX解析器比使用DOM解析器有优势,反之亦然?DOM解析器和SAX解析器的通常应用程序是什么?
在以下情况下,使用SAX解析器比使用DOM解析器更有利。
在以下情况下,使用DOM解析器比使用SAX解析器更有利。
示例(使用DOM解析器还是SAX解析器?):
假设讲师拥有一个XML文档,其中包含学生的所有个人信息以及他的学生在课堂上提出的要点,现在他正在使用应用程序为学生分配最终成绩。他想生产的是带有SSN和等级的清单。我们还假设,在他的应用程序中,讲师没有使用诸如数组之类的数据结构来存储学生的个人信息和积分。如果讲师决定将A给予平均成绩或以上的人,将B给予其他人,那么他最好在其应用程序中使用DOM解析器。原因是他没有办法知道在处理整个文档之前,班级平均水平是多少。他可能需要在应用程序中做的是,首先浏览所有学生的 分并计算平均值,然后再次浏览文档,并通过将每个学生获得的得分与全班平均水平进行比较,将最终成绩分配给每个学生。但是,如果讲师采用这样的评分策略,将获得90分或以上的学生分配为A,将其他人分配为B,那么他最好使用SAX解析器。原因是,为每个学生分配最后的成绩,他不必等待整个文档被处理。一旦SAX解析器读取了该学生的分数,他就可以立即为该学生分配分数。在上面的分析中,我们假定教师没有创建自己的数据结构。如果他创建自己的数据结构,例如存储SSN的字符串数组和存储点的整数数组,该怎么办?在这种情况下,我认为SAX是更好的选择,在此之前它还可以节省内存和时间,但仍可以完成工作。好吧,这个例子还有一个考虑。如果教师想做的不是打印列表,而是将原始文档保存回去,并更新每个学生的成绩怎么办?在这种情况下,无论他采用哪种分级策略,DOM解析器都应该是一个更好的选择。他不需要创建自己的任何数据结构。他需要做的是首先修改DOM树(即,将值设置为“等级”节点),然后保存整个修改后的树。如果他选择使用SAX解析器而不是DOM解析器,则在这种情况下,他必须创建一个数据结构,该数据结构几乎像DOM树一样复杂,然后才能完成工作。尚未完成工作。好吧,这个例子还有一个考虑。如果教师想做的不是打印列表,而是将原始文档保存回去,并更新每个学生的成绩怎么办?在这种情况下,无论他采用哪种分级策略,DOM解析器都应该是一个更好的选择。他不需要创建自己的任何数据结构。他需要做的是首先修改DOM树(即,将值设置为“等级”节点),然后保存整个修改后的树。如果他选择使用SAX解析器而不是DOM解析器,则在这种情况下,他必须创建一个数据结构,该数据结构几乎像DOM树一样复杂,然后才能完成工作。尚未完成工作。好吧,这个例子还有一个考虑。如果教师想做的不是打印列表,而是将原始文档保存回去,并更新每个学生的成绩怎么办?在这种情况下,无论他采用哪种分级策略,DOM解析器都应该是一个更好的选择。他不需要创建自己的任何数据结构。他需要做的是首先修改DOM树(即,将值设置为“等级”节点),然后保存整个修改后的树。如果他选择使用SAX解析器而不是DOM解析器,则在这种情况下,他必须创建一个数据结构,该数据结构几乎像DOM树一样复杂,然后才能完成工作。但是要保存原始文档并更新每个学生的成绩?在这种情况下,无论他采用何种分级策略,DOM解析器都应该是一个更好的选择。他不需要创建自己的任何数据结构。他需要做的是首先修改DOM树(即,将值设置为“等级”节点),然后保存整个修改后的树。如果他选择使用SAX解析器而不是DOM解析器,则在这种情况下,他必须创建一个数据结构,该数据结构几乎像DOM树一样复杂,然后才能完成工作。但是要保存原始文档并更新每个学生的成绩?在这种情况下,无论他采用何种分级策略,DOM解析器都应该是一个更好的选择。他不需要创建自己的任何数据结构。他需要做的是首先修改DOM树(即,将值设置为“等级”节点),然后保存整个修改后的树。如果他选择使用SAX解析器而不是DOM解析器,则在这种情况下,他必须创建一个数据结构,该数据结构几乎像DOM树一样复杂,然后才能完成工作。节点),然后保存整个修改后的树。如果他选择使用SAX解析器而不是DOM解析器,则在这种情况下,他必须创建一个数据结构,该数据结构几乎像DOM树一样复杂,然后才能完成工作。节点),然后保存整个修改后的树。如果他选择使用SAX解析器而不是DOM解析器,则在这种情况下,他必须创建一个数据结构,该数据结构几乎像DOM树一样复杂,然后才能完成工作。
问题陈述:编写Java程序以提取有关圆的所有信息,这些圆是给定XML文档中的元素。我们假设每个圆元素都有三个子元素(即x,y和radius)以及一个color属性。示例文件如下:
<?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 a x element is seen set the flag as 1
flagX=1;
else if(rawName.equals("y")) // if a y 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>
start element:abc
,end element:abc
。当通过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
attr: "lang"
上方element: <title>
?纵观XML,它看起来像一个attr
应该平行于其<element>
与<book>
和category
。这仅仅是节省空间的技术,还是要建立亲子关系?
DOM代表文档对象模型,它以树格式表示XML文档,每个元素代表树枝。DOM解析器创建XML文件的“内存中”树表示形式,然后对其进行解析,因此,它需要更多的内存,并且建议增加DOM解析器的堆大小,以避免Java.lang.OutOfMemoryError:java堆空间。如果XML文件很小,则使用DOM解析器解析XML文件的速度非常快,但是如果您尝试使用DOM解析器读取大型XML文件,则很可能会花费很长时间甚至无法完全加载它,这仅仅是因为创建XML Dom Tree需要大量内存。Java提供了对DOM解析的支持,您可以使用DOM解析器解析Java中的XML文件。DOM类位于w3c.dom包中,而DOM Parser for Java则位于JAXP(用于XML解析的Java API)包中。
Java中的SAX XML解析器
SAX代表XML解析的简单API。这是基于事件的XML解析,它逐步解析XML文件,因此非常适合大型XML文件。当SAX XML Parser遇到打开标签,元素或属性且相应地进行解析时,将触发事件。建议使用SAX XML解析器来解析Java中的大型xml文件,因为它不需要加载Java中的整个XML文件,并且可以一小部分地读取大型XML文件。Java提供了对SAX解析器的支持,您可以使用SAX解析器解析Java中的任何xml文件。在此,我已经介绍了使用SAX解析器读取xml文件的示例。在Java中使用SAX Parser的一个缺点是,与DOM Parser相比,使用SAX Parser读取Java中的XML文件需要更多代码。
DOM和SAX XML分析器之间的区别
以下是Java中DOM解析器和SAX解析器之间的一些高级差异:
1)DOM解析器将整个xml文档加载到内存中,而SAX仅将一小部分XML文件加载到内存中。
2)DOM解析器比SAX更快,因为它可以访问内存中的整个XML文档。
3)Java中的SAX解析器比DOM解析器更适合大型XML文件,因为它不需要太多内存。
4)DOM解析器可用于文档对象模型,而SAX是基于事件的xml解析器。
了解更多:http : //javarevisited.blogspot.com/2011/12/difference-between-dom-and-sax-parsers.html#ixzz2uz1bJQqZ
SAX和DOM都用于解析XML文档。两者都有优点和缺点,可以根据情况在我们的编程中使用
SAX:
逐节点解析
不将XML存储在内存中
我们无法插入或删除节点
上下移动
DOM
在处理之前将整个XML文档存储到内存中
占用更多内存
我们可以插入或删除节点
沿任何方向移动。
如果我们需要找到一个节点并且不需要插入或删除,则可以使用SAX本身,否则可以使用DOM,只要我们有更多的内存即可。
1)DOM解析器将整个XML文档加载到内存中,而SAX仅将XML文件的一小部分加载到内存中。
2)DOM解析器比SAX更快,因为它可以访问内存中的整个XML文档。
3)Java中的SAX解析器比DOM解析器更适合大型XML文件,因为它不需要太多内存。
4)DOM解析器可用于文档对象模型,而SAX是基于事件的XML解析器。
了解更多:http : //javarevisited.blogspot.com/2011/12/difference-between-dom-and-sax-parsers.html#ixzz498y3vPFR