在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; }
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是非常好的选择。