您的位置:首页 > 其它

sax解析XML

2011-03-31 13:45 162 查看
JAVA
解析
XML
通常有两种方式,
DOM

SAX

DOM
虽然是
W3C
的标准,提供了标准的解析方式,但它的解析效率一直不尽如人意,因为使用
DOM
解析
XML
时,解析器读入整个文档并构建一个驻留内存的树结构(节点树),然后您的代码才可以使用
DOM
的标准接口来操作这个树结构。但大部分情况下我们只对文档的部分内容感兴趣,根本就不用先解析整个文档,并且从节点树的根节点来索引一些我们需要的数据也是非常耗时的。

SAX
是一种
XML
解析的替代方法。相比于文档对象模型
DOM

SAX
是读取和操作
XML
数据的更快速、更轻量的方

法。
SAX
允许您在读取文档时处理它,从而不必等待整个文档被存储之后才采取操作。它不涉及
DOM
所必需的开销和概念跳跃。
SAX API
是一个基于事件的
API
,适用于处理数据流,即随着数据的流动而依次处理数据。
SAX API

在其解析您的文档时发生一定事件的时候会通知您。在您对其响应时,您不作保存的数据将会
被抛弃。


SAX
中有
4
个处理器是要实现的:
ContentHandler

DTDHandler

EntityResolver

ErrorHandler
,以处理不同的事件,这是比较麻烦的,

幸好
SAX
定义了一个
DefaultHandler
类把这几个实现了,我们只需在
DefaultHandler
中定义事件处理方法,然后注册到
XMLReader
,而
SAXParser
封装了
XMLReader
的实现类,

SAXParser
又是由
SAXParserFactory
提供的,所以我们实际用到的类只有:
SAXParserFactory

SAXParser

DefaultHandler

SAX
的解析步骤:


1
)写一个类继承
DefaultHandler,
实现自己的事件处理方法


2
)在主程序中建立
SAXParserFactory


3
)可以设置这个
factory
的参数


4
)从这个
factory
得到
SAXParser


5
)解析
XML
文件

例子:

XML
文件:
hr.xml

<?xml version="1.0"
encoding="GB2312" ?>

<!--
个人履历表
-->

<resume>

<person id="01">

<name>
张三
</name>

<birthday>03/24/1975</birthday>

<phone>1111-1111</phone>

<address>
大连
</address>

</person>

<person id="02">

<name>
李四
</name>

<birthday>9/26/1978</birthday>

<phone>2222-2222</phone>

<address>
南京
</address>

</person>

<person id="03">

<name>
王五
</name>

<birthday>11/09/1979</birthday>

<phone>3333-3333</phone>

<address>
武汉
</address>

</person>

</resume>

import javax.xml.parsers.*;

import org.xml.sax.*;

import org.xml.sax.helpers.*;

public class MySaxParser extends DefaultHandler
{

public static void main(String[] args) {

try {

// 创建一个handler

DefaultHandler dh = new MySaxParser();

// 创建SAXParserFactory

SAXParserFactory spf = SAXParserFactory.newInstance();

// 从factory 中得到SAXParser

SAXParser sp = spf.newSAXParser();

// 用自定义的handler 解析xml

sp.parse("08_02.xml", dh);

} catch (Exception e) {

e.printStackTrace();

}

}

public void startDocument() {

}

/**

* 当开始一个元素时打印出元素名和此元素的所有属性

*/

public void startElement(String uri, String localName, String qName,

Attributes attributes) {

System.out.print(qName + ":");

int len = 0;

len = attributes.getLength();

if (len > 0) {

System.out.print("/t" + "attributes: ");

for (int i = 0; i < len; i++)

System.out.print(attributes.getQName(i) + "="

+ attributes.getValue(i) + "/t");

// System.out.println();

}

}

/**

* 打印出元素内容

*/

public void characters(char[] ch, int start, int length) {

String s = String.valueOf(ch, start, length);

System.out.print(s);

}

public void endElement(String uri, String localName, String qName) {

}

public void endDocument() {

}

}

SAX API
里面所有主要的事件解析方法吧。(
实际上
DefaultHandler
就是实现了上面的四个事件处理器接口,然后提供了每个抽象方法的默认实现。)

ContentHandler
接口
:接收文档逻辑内容的通知
的处理器接口。

import org.xml.sax.Attributes;

import org.xml.sax.ContentHandler;

import org.xml.sax.Locator;

import org.xml.sax.SAXException;

class MyContentHandler implements
ContentHandler{

/*

*
接收文档的开始的通知。

*/

@Override

public
void startDocument() throws SAXException {

}

/*

*
接收文档的结尾的通知。

*/

@Override

public
void endDocument() throws SAXException {

}

/*

*
接收字符数据的通知。

*

DOM


ch[begin:end]
相当于
Text
节点的节点值(
nodeValue


*/

@Override

public
void characters(char[] ch, int begin, int length) throws SAXException {

}

/*

*
接收元素开始的通知。

*
参数意义如下:

* uri
:元素的命名空间

*
localName
:元素的本地名称(不带前缀)

*
qName
:元素的限定名(带前缀)

*
atts
:元素的属性集合

*/

@Override

public
void startElement(String uri, String localName, String qName,

Attributes
atts) throws SAXException {

}

/*

*
接收文档的结尾的通知。

*
参数意义如下:

* uri
:元素的命名空间

*
localName
:元素的本地名称(不带前缀)

*
qName
:元素的限定名(带前缀)

*

*/

@Override

public
void endElement(String uri,String localName,String qName)

throws
SAXException {

}

/*

*
开始前缀
URI
名称空间范围映射。

*
此事件的信息对于常规的命名空间处理并非必需:

*

http://xml.org/sax/features/namespaces 功能为
true
(默认)时,

* SAX XML
读取器将自动替换元素和属性名称的前缀。

*
参数意义如下:

*
prefix
:前缀

* uri
:命名空间

*/

@Override

public
void startPrefixMapping(String prefix,String uri)

throws
SAXException {

}

/*

*
结束前缀
URI
范围的映射。

*/

@Override

public
void endPrefixMapping(String prefix) throws SAXException {

}

/*

*
接收元素内容中可忽略的空白的通知。

*
参数意义如下:

* ch
:
来自
XML
文档的字符

*
start :
数组中的开始位置

*
length :
从数组中读取的字符的个数

*/

@Override

public
void ignorableWhitespace(char[] ch, int begin, int length)

throws
SAXException {

}

/*

*
接收处理指令的通知。

*
参数意义如下:

*
target :
处理指令目标

*
data :
处理指令数据,如果未提供,则为
null


*/

@Override

public
void processingInstruction(String target,String data)

throws
SAXException {

}

/*

*
接收用来查找
SAX
文档事件起源的对象。

*
参数意义如下:

*
locator :
可以返回任何
SAX
文档事件位置的对象

*/

@Override

public
void setDocumentLocator(Locator locator) {

}

/*

*
接收跳过的实体的通知。

*
参数意义如下:

*
name :
所跳过的实体的名称。如果它是参数实体,则名称将以
'%'
开头,

*

如果它是外部
DTD
子集,则将是字符串
"[dtd]"

*/

@Override

public
void skippedEntity(String name) throws SAXException {

}

}

DTDHandler
接口
:接收与
DTD
相关的事件的通知的处理器接口。

import org.xml.sax.DTDHandler;

import org.xml.sax.SAXException;

public class MyDTDHandler implements
DTDHandler {

/*

*
接收注释声明事件的通知。

*
参数意义如下:

*
name -
注释名称。

*
publicId -
注释的公共标识符,如果未提供,则为
null


*
systemId -
注释的系统标识符,如果未提供,则为
null


*/

@Override

public
void notationDecl(String name, String publicId, String systemId)

throws
SAXException {

}

/*

*
接收未解析的实体声明事件的通知。

*
参数意义如下:

*
name -
未解析的实体的名称。

* publicId -
实体的公共标识符,如果未提供,则为

null


*
systemId -
实体的系统标识符。

*
notationName -
相关注释的名称。

*/

@Override

public
void unparsedEntityDecl(String name,String publicId,String systemId,

String notationName) throws SAXException {

}

}

EntityResolver
接口
:是用于解析实体的基本接口。

import java.io.IOException;

import org.xml.sax.EntityResolver;

import org.xml.sax.InputSource;

import org.xml.sax.SAXException;

public class MyEntityResolver implements
EntityResolver {

/*

*
允许应用程序解析外部实体。

*
解析器将在打开任何外部实体(顶级文档实体除外)前调用此方法

*
参数意义如下:

*
publicId

被引用的外部实体的公共标识符,如果未提供,则为
null


*
systemId

被引用的外部实体的系统标识符。

*
返回:

*
一个描述新输入源的

InputSource
对象,或者返回
null


*
以请求解析器打开到系统标识符的常规
URI
连接。

*/

@Override

public
InputSource resolveEntity(String publicId, String systemId)

throws SAXException, IOException {

return
null;

}

}

ErrorHandler
接口
:是错误处理程序的基本接口。

import org.xml.sax.ErrorHandler;

import org.xml.sax.SAXException;

import org.xml.sax.SAXParseException;

public class MyErrorHandler implements
ErrorHandler {

/*

*
接收可恢复的错误的通知

*/

@Override

public
void error(SAXParseException e) throws SAXException {

}

/*

*
接收不可恢复的错误的通知。

*/

@Override

public
void fatalError(SAXParseException e) throws SAXException {

}

/*

*
接收不可恢复的错误的通知。

*/

@Override

public
void warning(SAXParseException e) throws SAXException {

}

}

Test
类的主方法打印解析
books.xml
时的事件信息。

import java.io.FileNotFoundException;

import java.io.FileReader;

import java.io.IOException;

import org.xml.sax.ContentHandler;

import org.xml.sax.DTDHandler;

import org.xml.sax.EntityResolver;

import org.xml.sax.ErrorHandler;

import org.xml.sax.InputSource;

import org.xml.sax.SAXException;

import org.xml.sax.XMLReader;

import
org.xml.sax.helpers.XMLReaderFactory;

public class Test {

public
static void main(String[] args) throws SAXException,

FileNotFoundException,
IOException {

//
创建处理文档内容相关事件的处理器

ContentHandler
contentHandler = new MyContentHandler();

//
创建处理错误事件处理器

ErrorHandler
errorHandler = new MyErrorHandler();

//
创建处理
DTD
相关事件的处理器

DTDHandler
dtdHandler = new MyDTDHandler();

//
创建实体解析器

EntityResolver
entityResolver = new MyEntityResolver();

//
创建一个
XML
解析器(通过
SAX
方式读取解析
XML


XMLReader
reader = XMLReaderFactory.createXMLReader();

/*

*
设置解析器的相关特性

* http://xml.org/sax/features/validation = true
表示开启验证特性

* http://xml.org/sax/features/namespaces = true
表示开启命名空间特性

*/

reader.setFeature("http://xml.org/sax/features/validation",true);

reader.setFeature("http://xml.org/sax/features/namespaces",true);

//
设置
XML
解析器的处理文档内容相关事件的处理器

reader.setContentHandler(contentHandler);

//
设置
XML
解析器的处理错误事件处理器

reader.setErrorHandler(errorHandler);

//
设置
XML
解析器的处理
DTD
相关事件的处理器

reader.setDTDHandler(dtdHandler);

//
设置
XML
解析器的实体解析器

reader.setEntityResolver(entityResolver);

//
解析
books.xml
文档

reader.parse(new
InputSource(new FileReader("books.xml")));

}

}

books.xml
文件的内容如下:

<?xml version="1.0"
encoding="GB2312"?>

<books
count="3" xmlns="http://test.org/books">

<!--books's
comment-->

<book
id="1">

<name>Thinking
in JAVA</name>

</book>

<book
id="2">

<name>Core
JAVA2</name>

</book>

<book
id="3">

<name>C++
primer</name>

</book>

</books>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: