SAX是一个解析速度快并且占用内存少的xml解析器,非常适合用于Android等移动设备。SAX解析XML文件采用的是事件驱动,也就是说,它并不需要解析完整个文档,在按内容顺序解析文档的过程中,SAX会判断当前读到的字符是否合法XML语法中的某部分,如果符合就会触发事件。所谓事件,其实就是一些回调(callback)方法,这些方法(事件)定义在ContentHandler接口。下面是一些ContentHandler接口常用的方法:
startDocument():当遇到文档的开头的时候,调用这个方法,可以在其中做一些预处理的工作。
endDocument():和上面的方法相对应,当文档结束的时候,调用这个方法,可以在其中做一些善后的工作。
startElement(String namespaceURI,String localName,String qName,Attributes atts)
当读到一个开始标签的时候,会触发这个方法。namespaceURI就是命名空间,localName是不带命名空间前缀的标签名,qName是带命名空间前缀的标签名。通过atts可以得到所有的属性名和相应的值。要注意的是SAX中一个重要的特点就是它的流式处理,当遇到一个标签的时候,它并不会纪录下以前所碰到的标签,也就是说,在startElement()方法中,所有你所知道的信息,就是标签的名字和属性,至于标签的嵌套结构,上层标签的名字,是否有子元属等等其它与结构相关的信息,都是不得而知的,都需要你的程序来完成。这使得SAX在编程处理上没有DOM来得那么方便。
endElement(String uri,String name):这个方法和上面的方法相对应,在遇到结束标签的时候,调用这个方法。
characters(char[] ch,int start,int length) :这个方法用来处理在XML文件中读到的内容,第一个参数为文件的字符串内容,后面两个参数是读到的字符串在这个数组中的起始位置和长度,使用new String(ch,start,length)就可以获取内容。
注意:一个标签之间的字符比较多时,或者字符串中包含有”\n”等特殊字符时,就会出现字符丢失的现象。遇到这种问题不要怀疑SAX不能解析标签中含有”\n”或字符比较多的XML。实际上是我们写的Handler是有问题的。SAX在解析XML时,当遇到一个标签中的内容比较多时,就会多次调用characters。所以我们在写Handler时要考虑到这种情况。就不会丢字符了。以下是一种解决方案:新建一个临时变量temp,在调用characters方法中用temp接收数据,在endElement方法中把临时变量temp赋值给目标变量,并给临时变量temp清空,避免出现脏数据,这样就可以解决sax读取XML时不能读取换行符号后面的内容的问题。
ljq.xml 文件
<?
xml version="1.0" encoding="UTF-8"
?>
<
persons
>
person
id
="23"
name
>
李明
</
age
>
30
person
="20"
>
李向梅
>
25
>
实体类
package
com.ljq.entity;
import
java.io.Serializable;
/**
* 实体类 * *
@author
jiqinlin *
*/
@SuppressWarnings(
"
serial
"
)
public
class
Person
implements
Serializable{
private
Integer id;
private
String name;
private
Short age;
public
Person() { }
public
Person(String name,Short age) {
super
();
this
.name
=
name;
this
.age
=
age; }
public
Integer getId() {
return
id; }
void
setId(Integer id) {
this
.id
=
id; }
public
String getName() {
return
name; }
void
setName(String name) {
this
.name
=
name; }
public
Short getAge() {
return
age; }
void
setAge(Short age) {
this
.age
=
age; } }
handle类
package
com.ljq.service;
import
java.util.ArrayList;
import
java.util.List;
import
org.xml.sax.Attributes;
import
org.xml.sax.SAXException;
import
org.xml.sax.helpers.DefaultHandler;
import
com.ljq.entity.Person;
class
XMLContentHandler
extends
DefaultHandler {
//
临时变量,解决sax读取XML时不能读取换行符号后面的内容的问题;注意temp=""不能写成temp或temp=null,避免脏数据
private
String temp
=
""
;
private
String preTag;
private
Person person;
private
List
<
Person
>
persons; @Override
void
startDocument()
throws
SAXException { persons
=
new
ArrayList
<
Person
>
(); } @Override
void
characters(
char
[] ch,
int
start,255); line-height:1.5!important">int
length)
throws
SAXException {
if
(person
!=
null
){ String date
=
new
String(ch,length);
if
(
"
name
"
.equals(preTag)) { temp
+=
date; }
else
if
(
"
age
"
.equals(preTag)) { temp
+=
date; } } } @Override
void
startElement(String uri,String name,Attributes attributes)
if
(
"
person
"
.equals(localName)) { person
=
new
Person(); person.setId(attributes.getIndex(
"
id
"
)); } preTag
=
localName; } @Override
void
endElement(String uri,String name)
if
(person
!=
null
&&
"
name
"
.equals(localName)) { person.setName(temp); temp
=
""
; }
null
&&
"
age
"
.equals(localName)) { person.setAge(
new
Short(temp)); temp
=
""
; }
null
&&
"
person
"
.equals(localName)) { persons.add(person); person
=
null
; } preTag
=
null
; }
getter...
public
List
<
Person
>
getPersons() {
return
persons; } }