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>
解析
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>
相关文章推荐
- XML解析的两种方式DOM和SAX
- XML学习总结-DOM和SAX解析-综合案例-(四)
- Android 使用Dom与SAX解析xml文档的方式
- sax解析xml案例
- android之XML文件解析 -- SAX
- 用SAXReader解析xml文档
- Java用SAX解析XML
- DOM与SAX解析xml的区别
- XML - 十分钟了解XML结构以及DOM和SAX解析方式
- SAX方式,simpleXML方式解析XML以及DOM方式和SAX方式的异同
- 通过SAX和PULL解析XML
- XML两种解析方式:SAX和DOM性能对比
- SAX解析XML文档
- SAX 解析XML 文件
- javaweb(一):sax解析xml
- android解析XML总结(SAX、Pull、Dom三种方式)
- SAX解析XML文档——(二)
- 解析XML(三种解析方式DOM,SAX,PULL)
- 解析xml之--SAX
- 用SAX方式解析XML(使用Dom4J工具)--第二天