DOM
(Document Object Model
)是处理XML
数据的传统方法,但其将整个XML
文件读取并以树状结构加载至内存中的工作方式非常消耗资源,尤其是在操作大文件时,就尤为显得低效、缓慢。作为一种替代技术的SAX
(Simple API for XML
),其自身的数据处理机制允许你在读取文档时进行处理,从而不必等待整个文档被存储后才采取操作。
SAX
在读取XML
流的同时去处理他们,参考下面的XML
片段:
<?xml version=”1.0” ?>
<user>
<name>Chris</name>
<sex>male</sex>
</user>
分析这个代码片段的SAX处理器将产生以下事件:
1. Start document
2. Start element (user)
3. Characters (white space)
4. Start element (name)
5. Characters (Chris)
6. End element (name)
7. Characters (white space)
8. Start element (sex)
9. Characters (male)
10. End element (sex)
11. Characters (white space)
12. End element (user)
SAX的处理涉及以下步骤:
1. 创建一个事件处理程序;
2. 创建SAX解析器;
3. 向解析器分配事件处理程序;
4. 解析文档,同时向事件处理程序发送每个事件。
这种基于事件的处理,应用程序可以不必解析整个文档,可以在某个条件得到满足时停止解析;应用程序是在读取时检查数据,因此不需要将数据存储在内存中,这对于大型文档来说是个巨大的优点,但也是由于该特点,使用SAX来更改数据或在数据流中往后移也是不可能的。
DOM由于树状结构在内存中是持久的,因此可以对数据和结构作出更改,还可以在树中上下导航,使用起来要简便的多;但由于在内存中构造树涉及大量的开销,创建DOM树可能是一个缓慢的过程。
SAX和DOM也并不是互相排斥的,可以使用DOM来创建SAX事件流,也可以使用SAX来创建DOM树,很多创建DOM树的解析器都是使用SAX来完成这个任务的。
SAX使用
1. 创建事件处理程序
在使用SAX处理XML之前,必须创建一个事件处理程序。SAX提供了一个DefaultHandler类,可以从该类扩展。
2. 创建解析器XMLReader
要使用XML文档做任何事情,都需要通过解析器读取其中的信息,可以通过SAXParserFactory和SAXParser来创建解析器。
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser parser = factory.newSAXParser();
XMLReader reader = parser.getXMLReader();
3. 验证与非验证解析器
解析器分为两种类型:非验证和验证。验证解析器根据已定义的语法检查XML文档的内容和结构,通过验证的文档被认为是有效的文档;非验证解析器则忽略此验证操作。可通过设置validating属性关闭SAXParserFactory创建的解析器的验证特性:
Factory.setValidating(false);
4. 设置内容处理程序
解析器将它的时间发送到一个ContentHandler,DefaultHandler扩展了ContentHandler。可通过XMLReader的setContentHandler()方法来指定。
5. 解析InputSource
解析xml文档需要一个InputSource,它包装了要处理的数据,XMLReader的parse()方法接受包装了文件的InputSource,同时将每个事件发送给ContentHandler。
InputSource source = new InputSource(“test.xml”);
Reader.parse(source);
6. 设置ErrorHandler
可以通过ErrorHandler来处理解析数据所遇到的错误,DefaultHandler也继承了ErrorHandler,可通过XMLReader的setErrorHandler()方法来指定。
常用的事件
1. startDocument()
使用该事件来开始文档,但不做任何事情,该事件会抛出一个SAXException。
2. startElement()
元素开始的事件。解析器将每个元素的信息传递给该事件,包括:
· 限定名称或qName
名称空间信息(若存在)和元素的实际名陈的组合,如存在名称空间,则包括冒号(:)。
· 名称空间URI
表示名称空间的URI。
· 本地名称localName
元素的实际名称。如果元素没有名称空间信息,解析器可能无法确定qName的哪个部分是localName。
· 属性Attributes
元素属性的对象集合。
3. endElement()
元素结束的事件。
4.Characters()
获得元素后,通过该事件来检索实际的数据。方法签名是:
public void characters(char[] ch, int start, int length) throws SAXException
ch字符数组包括整个文档,可通过起始和长度信息来获取当前元素的字符。
5. ignorableWhitespace()
解析器不是在Characters()中将文档的空白字符床地给内容处理程序的,而是在ignorableWhitespace()事件中传递的。
6. endDocument()
该事件用于处理文档解析完成。
7. ErrorHandler
ErrorHandler也有预定义用于处理错误的事件,包括:warning, error, fatalError。
8. XMLFilters
由于SAX在读取数据时分析数据,可以通过XMLFilters在分析数据之前对数据进行更改。