概述:
PULL解析器小巧轻便,解析速度快,简单易用,非常适合在Android移动设备中使用,Android系统内部在解析各种XML时也是用PULL解析器,Android官方推荐开发者们使用Pull解析技术。Pull解析技术是第三方开发的开源技术,它同样可以应用于JavaSE开发。
PULL 的工作原理:
XML pull提供了开始元素和结束元素。当某个元素开始时,可以调用parser.nextText从XML文档中提取所有字符数据。当解析到一个文档结束时,自动生成EndDocument事件。
常用的XML pull的接口和类:
XmlPullParser:该解析器是一个在org.xmlpull.v1中定义的解析功能的接口。
XmlSerializer:它是一个接口,定义了XML信息集的序列。
XmlPullParserFactory:这个类用于在XMPULL V1 API中创建XML Pull解析器。
XmlPullParserException:抛出单一的XML pull解析器相关的错误。
PULL解析器的运行方式和SAX类似,都是基于事件的模式。
不同的是,在PULL解析过程中返回的是数字,且我们需要自己获取产生的事件然后做相应的操作,而不像SAX那样由处理器触发一种事件的方法,执行我们的代码:
读取到xml的声明返回 START_DOCUMENT; 结束返回 END_DOCUMENT ; 开始标签返回 START_TAG;
结束标签返回 END_TAG; 文本返回 TEXT。
几种解析技术的比较与总结:
对于Android的移动设备而言,因为设备的资源比较宝贵,内存是有限的,所以我们需要选择适合的技术来解析XML,这样有利于提高访问的速度。
DOM在处理XML文件时,将XML文件解析成树状结构并放入内存中进行处理。当XML文件较小时,我们可以选DOM,因为它简单、直观。
SAX则是以事件作为解析XML文件的模式,它将XML文件转化成一系列的事件,由不同的事件处理器来决定如何处理。XML文件较大时,选择SAX技术是比较合理的。虽然代码量有些大,但是它不需要将所有的XML文件加载到内存中。这样对于有限的Android内存更有效,而且Android提供了一种传统的SAX使用方法以及一个便捷的SAX包装器。 使用Android.util.Xml类,从示例中可以看出,会比使用 SAX来得简单。
XML pull解析并未像SAX解析那样监听元素的结束,而是在开始处完成了大部分处理。这有利于提早读取XML文件,可以极大的减少解析时间,这种优化对于连接速度较漫的移动设备而言尤为重要。对于XML文档较大但只需要文档的一部分时,XML Pull解析器则是更为有效的方法。
开发实例:
在asset定义了books.xml文件,对于它,只要是一份格式良好的xml文档即可,具体内容根据需要定义。
读取XML:从定义好的books.xml文件解析并显示出来;
写入XML:将解析后的内容再写入到本地,这里也保存为名字为books.xml的文件。
例如:books.xml定义如下形式:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
<?
xml
version
=
"1.0"
encoding
=
"utf-8"
?>
<
books
>
<
book
>
<
id
>1001</
id
>
<
name
>Thinking In Java</
name
>
<
price
>80.00</
price
>
</
book
>
<
book
>
<
id
>1002</
id
>
<
name
>Core Java</
name
>
<
price
>90.00</
price
>
</
book
>
<
book
>
<
id
>1003</
id
>
<
name
>Hello, Andriod</
name
>
<
price
>100.00</
price
>
</
book
>
</
books
>
|
完整代码:
PULLParserActivity:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
|
package
com.xsjayz.xml;
import
java.io.FileOutputStream;
import
java.io.InputStream;
import
java.util.List;
import
android.app.Activity;
import
android.content.Context;
import
android.os.Bundle;
import
android.util.Log;
import
android.view.View;
import
android.widget.Button;
import
android.widget.TextView;
/**
* PULL解析器,这里只是简单的定义了一个TextView显示解析结果,两个Button操作。
*
* @since 2012-08-23
*/
public
class
PULLParserActivity
extends
Activity {
private
static
final
String TAG =
"XML"
;
private
TextView textView =
null
;
private
Button readBtn =
null
;
private
Button writeBtn =
null
;
private
BookParser parser;
private
List<Book> booksList;
@Override
public
void
onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
setContentView(R.layout.main);
textView = (TextView) findViewById(R.id.txt);
readBtn = (Button) findViewById(R.id.read_btn);
writeBtn = (Button) findViewById(R.id.write_btn);
readBtn.setOnClickListener(
new
View.OnClickListener() {
@Override
public
void
onClick(View v) {
try
{
InputStream is = getAssets().open(
"books.xml"
);
parser =
new
PULLBookParser();
booksList = parser.parse(is);
for
(Book book : booksList) {
Log.i(TAG, book.toString());
}
for
(Book book : booksList) {
textView.setText(textView.getText() + book.toString());
}
}
catch
(Exception e) {
Log.e(TAG, e.getMessage());
}
}
});
writeBtn.setOnClickListener(
new
View.OnClickListener() {
@Override
public
void
onClick(View v) {
try
{
String xmlString = parser.serialize(booksList);
// 序列化
FileOutputStream fos = openFileOutput(
"books.xml"
,
Context.MODE_PRIVATE);
fos.write(xmlString.getBytes(
"UTF-8"
));
}
catch
(Exception e) {
Log.e(TAG, e.getMessage());
}
}
});
}
}
|
PULLBookParser:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
|
package
com.xsjayz.xml;
import
java.io.InputStream;
import
java.io.StringWriter;
import
java.util.ArrayList;
import
java.util.List;
import
org.xmlpull.v1.XmlPullParser;
import
org.xmlpull.v1.XmlSerializer;
import
android.util.Xml;
/**
* PULL解析器,实现了BookParser接口
*/
public
class
PULLBookParser
implements
BookParser {
/**
* @param is
* @return booksList
*/
@Override
public
List<Book> parse(InputStream is)
throws
Exception {
List<Book> booksList =
null
;
Book book =
null
;
// 由android.util.Xml创建一个XmlPullParser实例
XmlPullParser parser = Xml.newPullParser();
// 设置输入流 并指明编码方式
parser.setInput(is,
"UTF-8"
);
// 产生第一个事件
int
eventType = parser.getEventType();
while
(eventType != XmlPullParser.END_DOCUMENT) {
switch
(eventType) {
// 判断当前事件是否为文档开始事件
case
XmlPullParser.START_DOCUMENT:
booksList =
new
ArrayList<Book>();
// 初始化books集合
break
;
// 判断当前事件是否为标签元素开始事件
case
XmlPullParser.START_TAG:
if
(parser.getName().equals(
"book"
)) {
// 判断开始标签元素是否是book
book =
new
Book();
}
else
if
(parser.getName().equals(
"id"
)) {
eventType = parser.next();
// 得到book标签的属性值,并设置book的id
book.setId(Integer.parseInt(parser.getText()));
}
else
if
(parser.getName().equals(
"name"
)) {
// 判断开始标签元素是否是book
eventType = parser.next();
book.setName(parser.getText());
}
else
if
(parser.getName().equals(
"price"
)) {
// 判断开始标签元素是否是price
eventType = parser.next();
book.setPrice(Float.parseFloat(parser.getText()));
}
break
;
// 判断当前事件是否为标签元素结束事件
case
XmlPullParser.END_TAG:
if
(parser.getName().equals(
"book"
)) {
// 判断结束标签元素是否是book
booksList.add(book);
// 将book添加到books集合
book =
null
;
}
break
;
}
// 进入下一个元素并触发相应事件
eventType = parser.next();
}
return
booksList;
}
/**
* @param books
* @return writer.toString()
*/
@Override
public
String serialize(List<Book> books)
throws
Exception {
// 由android.util.Xml创建一个XmlSerializer实例
XmlSerializer serializer = Xml.newSerializer();
StringWriter writer =
new
StringWriter();
// 设置输出方向为writer
serializer.setOutput(writer);
serializer.startDocument(
"UTF-8"
,
true
);
serializer.startTag(
""
,
"books"
);
for
(Book book : books) {
serializer.startTag(
""
,
"book"
);
serializer.attribute(
""
,
"id"
, book.getId() +
""
);
serializer.startTag(
""
,
"name"
);
serializer.text(book.getName());
serializer.endTag(
""
,
"name"
);
serializer.startTag(
""
,
"price"
);
serializer.text(book.getPrice() +
""
);
serializer.endTag(
""
,
"price"
);
serializer.endTag(
""
,
"book"
);
}
serializer.endTag(
""
,
"books"
);
serializer.endDocument();
return
writer.toString();
}
}
|
BookParser:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
package
com.xsjayz.xml;
import
java.io.InputStream;
import
java.util.List;
public
interface
BookParser {
/**
* 解析输入流 得到Book对象集合
*
* @param is
* @throws Exception
*/
public
List<Book> parse(InputStream is)
throws
Exception;
/**
* 序列化Book对象集合 得到XML形式的字符串
*
* @param books
* @throws Exception
*/
public
String serialize(List<Book> books)
throws
Exception;
}
|
Book:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
package
com.xsjayz.xml;
/**
* Book的model类,定义了Book的所有状态,访问器和修改器,重写了toString方法
*/
public
class
Book {
private
int
id;
private
String name;
private
float
price;
public
int
getId() {
return
id;
}
public
void
setId(
int
id) {
this
.id = id;
}
public
String getName() {
return
name;
}
public
void
setName(String name) {
this
.name = name;
}
public
float
getPrice() {
return
price;
}
public
void
setPrice(
float
price) {
this
.price = price;
}
@Override
public
String toString() {
return
"id:"
+ id +
"\nname:"
+ name +
"\nprice:"
+ price +
"\n"
;
}
}
|