浅析PULL解析
1. 基本介绍
PULL方式解析XML是在Android中极力推荐使用的一种解析XML的方式,但PULL解析除了在Android中可以使用外,在JavaSE中仍然可以使用。
在JavaSE中,我们要使用PULL解析XML,首先得获取XmlPull所需要的类库及依赖类库:
类库Jar包下载地址:
http://www.findjar.com/jar/xmlpull/xmlpull/1.1.3.4a/xmlpull-1.1.3.4a.jar.html
http://sourceforge.net/projects/kxml/
2. PULL解析
在XmlPull的API类库中,我们可以看到,其实XmlPull非常简单,主要包含了两个接口,一个类,一个异常,实际我们在使用过程中,用得最多的是XmlPullParser接口中的方法。
PULL解析简单易用,因为XmlPullParser接口中只需要调用一个next方法就可以获取下一个事件类型,并且只有五种事件类型:
- START_DOCUMENT:文档开始,解析器还未读取到任何输入的时候
- START_TAG:解析到开始标签
- TEXT:解析到文本节点
- END_TAG:解析到结束标签
- END_DOCUMENT:文档结束
2.1 XmlPullParser常用方法
// 获取指定索引属性的属性值,索引从0开始
public abstract String getAttributeValue (int index);
// 返回当前事件类型
public abstract int getEventType ();
// 返回当前事件类型的内容字符串形式
public abstract String getText ();
// 获取下一个解析事件类型
public abstract int next ();
// 当前是开始标签,如果下一个元素为文本,则返回该文本字符串,
// 如果下一个元素是结束标签,则返回空字符串,其它情况将抛出异常
public abstract String nextText ();
// 设置即将被解析的输入流
public abstract void setInput (InputStream inputStream,String inputEncoding);
2.2 解析步骤
下面我们一步一步地实现PULL解析。
首先,我们需要创建一个解析器对象,解析器对象的创建是通过解析器工厂对象获取到的:
// 创建解析器工厂对象
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
// 从工厂中获取解析器对象
XmlPullParser parser = factory.newPullParser();
接下来我们设置解析器的输入流:
// 设置解析器输入流
parser.setInput(in,encode);
接着我们就可以开始解析xml了。
在PULL解析的典型应用中,我们一般会重复调用next()方法获取下一个事件类型,然后处理,直到事件类型为END_DOCUMENT为止。
/* 解析 */
// 获取解析到的事件类型
int eventType = parser.getEventType();
// 未解析到文档结尾,则循环解析
while (eventType != XmlPullParser.END_DOCUMENT) {
switch (eventType) {
case XmlPullParser.START_DOCUMENT: // 文档开始事件
emps = new ArrayList<Employee>();
break;
case XmlPullParser.START_TAG: // 开始标签事件
String nodeName = parser.getName().trim();
if ("employee".equals(nodeName)) { // employee节点
emp = new Employee();
// 该节点有id属性,则获取id属性
int id = Integer.parseInt(parser.getAttributeValue(null,"id"));
emp.setId(id);
} else if ("name".equals(nodeName)) {
String name = parser.nextText().trim();
emp.setName(name);
} else if ("age".equals(nodeName)) {
int age = Integer.parseInt(parser.nextText().trim());
emp.setAge(age);
} else if ("address".equals(nodeName)) {
String address = parser.nextText();
emp.setAddress(address);
}
break;
case XmlPullParser.END_TAG: // 结束标签事件
if ("employee".equals(parser.getName().trim())) {
emps.add(emp);
emp = null;
}
break;
}
eventType = parser.next(); // 切换到下一个解析事件
}
完整示例:
xml文件:
<employees>
<employee id="1">
<name>小明</name>
<age>29</age>
<address>四川成都</address>
</employee>
<employee id="2">
<name>老骆</name>
<age>35</age>
<address>四川成都</address>
</employee>
</employees>
员工类:
package com.demo5;
/** * 员工类 * * @author 小明 * */
public class Employee {
private int id;
private String name;
private int age;
private String address;
public Employee() {
super();
}
public Employee(int id,String name,int age,String address) {
super();
this.id = id;
this.name = name;
this.age = age;
this.address = address;
}
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 int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "Employee [id=" + id + ",name=" + name + ",age=" + age
+ ",address=" + address + "]";
}
}
解析服务类:
package com.demo5;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;
/** * 服务类 * @author 小明 * */
public class Service {
/** * 读取XML解析 * * @param in * xml文件流 * @param encode * 文件编码 * @return */
public static List<Employee> readXml(InputStream in,String encode) {
List<Employee> emps = null;
Employee emp = null;
try {
// 创建解析器工厂对象
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
// 从工厂中获取解析器对象
XmlPullParser parser = factory.newPullParser();
// 设置解析器输入
parser.setInput(in,encode);
/* 解析 */
// 获取解析到的事件类型
int eventType = parser.getEventType();
// 未解析到文档结尾,则循环解析
while (eventType != XmlPullParser.END_DOCUMENT) {
switch (eventType) {
case XmlPullParser.START_DOCUMENT: // 文档开始事件
// 创建List集合对象
emps = new ArrayList<Employee>();
break;
case XmlPullParser.START_TAG: // 标签开始事件
String nodeName = parser.getName().trim(); // 节点名称
if ("employee".equals(nodeName)) { // employee节点
emp = new Employee(); // 创建员工对象
// 该节点有id属性,则获取id属性
int id = Integer.parseInt(parser.getAttributeValue(
null,"id"));
emp.setId(id);
} else if ("name".equals(nodeName)) { // name节点
String name = parser.nextText().trim();
emp.setName(name);
} else if ("age".equals(nodeName)) { // age节点
int age = Integer.parseInt(parser.nextText().trim());
emp.setAge(age);
} else if ("address".equals(nodeName)) { // address节点
String address = parser.nextText();
emp.setAddress(address);
}
break;
case XmlPullParser.END_TAG:
if ("employee".equals(parser.getName().trim())) {
emps.add(emp);
emp = null;
}
break;
}
eventType = parser.next(); // 切换到下一个解析事件
}
} catch (XmlPullParserException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return emps;
}
}
测试类:
package com.demo5;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.List;
public class Test {
public static void main(String[] args) throws FileNotFoundException {
InputStream in = new FileInputStream("demo.xml");
List<Employee> list = Service.readXml(in,"utf-8");
for (Employee employee : list) {
System.out.println(employee);
}
}
}