在Java开发中大家常用SAX或者DOM解析XML文件,两者的特点也很明显:SAX基于事件驱动,速度快,占用内存少;DOM一次性把文件读入内存中,以树的方式操作XML数据更灵活。
PULL是第三种优秀的XML解析方式,其工作原理和SAX类似,也是基于事件驱动的,SAX和PULL比较如下:
(1)相同点:
SAX/PULL都是基于事件的解析器。
解析速度快,占用内存少。
(2)区别:
以Android代码为例演示一下PULL方式读写XML的过程:SAX可认为是“PUSH“推模式。解析器遇到事件源时会将数据推送给内容处理器(ContentHandler),SAX解析,一旦开始解析就要解析完成,中途不能退出。
PULL拉模式,主动从解析器中获取自己感兴趣的事件,感觉数据像是”拉“下来的,PULL式解析过程中(while循环里)解析完感兴趣的数据之后可以退出循环。
例子XML文件test.xml:
<?xml version="1.0" encoding="UTF-8"?>
<persons>
<person id="23">
<name>lisi</name>
<age>30</age>
</person>
<person id="20">
<name>zhangsan</name>
<age>25</age>
</person>
</persons>
先定义个javabean来对应上面的xml文件的内容:
package com.tony.domain;
public class Person {
private int id;
private String name;
private int age;
public Person(){
}
public Person(int id, String name, int age) {
super();
this.id = id;
this.name = name;
this.age = age;
}
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;
}
@Override
public String toString() {
return "Person [id=" + id + ", name=" + name + ", age=" + age + "]";
}
}
读取xml文件代码:
public static List<Person> getPersonsFromXML(InputStream xml) throws Exception{
List<Person> persons = null;
Person person = null;
//Android中获取PULL XML解析器,也可以使用XmlPullParserFactory.newInstance().newPullParser();
XmlPullParser parser = Xml.newPullParser();
parser.setInput(xml, "UTF-8");
int event = parser.getEventType();
while(event != XmlPullParser.END_DOCUMENT){//和SAX类似,PULL也使用startDocument和endDocument事件来判断文件的开始和结束
switch(event){
case XmlPullParser.START_DOCUMENT:
persons = new ArrayList<Person>();
break;
case XmlPullParser.START_TAG://类似SAX的startElement事件,XML节点开始
if("person".equals(parser.getName())){
person = new Person();
person.setId(Integer.parseInt(parser.getAttributeValue(0)));
}
if("name".equals(parser.getName())){
person.setName(parser.nextText());
}
if("age".equals(parser.getName())){
person.setAge(Integer.parseInt(parser.nextText()));
}
break;
case XmlPullParser.END_TAG://类似SAX的endElement事件,XML节点结束
if("pserson".equals(parser.getName())){
persons.add(person);
person = null;
}
break;
}
event = parser.next();//获取解析器中下一个事件
}
return persons;
}
写xml代码:
public static void saveDataToXML(List<Person> persons, OutputStream os) throws Exception{
XmlSerializer serializer = Xml.newSerializer();
serializer.setOutput(os, "UTF-8");
serializer.startDocument("UTF-8", true);//第二个参数设置该xml是否为standalone
serializer.startTag(null, "persons");//第一个参数为命名空间
for(Person person : persons){
serializer.startTag(null, "person");
serializer.attribute(null, "id", Integer.toString(person.getId()));
serializer.startTag(null, "name");
serializer.text(person.getName());
serializer.endTag(null, "name");
serializer.startTag(null, "age");
serializer.text(Integer.toString(person.getAge()));
serializer.endTag(null, "age");
serializer.endTag(null, "person");
}
serializer.endTag(null, "persons");
serializer.endDocument();
os.flush();
os.close();
}
通过代码我们看到PULL方式与SAX方式解析xml代码非常的类似,在对于只处理xml中部分内容情况下,PULL是非常好的选择。