Pull解析器的运行方式与 SAX 解析器相似。它提供了类似的事件,如:开始元素和结束元素事件,使用parser.next()可以进入下一个元素并触发相应事件。跟SAX不同的是, Pull解析器产生的事件是一个数字,而非方法,因此可以使用一个switch对感兴趣的事件进行处理。当元素开始解析时,调用parser.nextText()方法可以获取下一个Text类型节点的值。
下面我们通过Demo例子来介绍如何使用PULL机制来解析XML文件。先看下如下工程的目录结构:
按以下步骤进行操作:
[1] 新建一个XML文件,命名为student.xml。同时把XML文件放置到assets目录下。student.xml文件的内容如下:
<?xml version="1.0" encoding="utf-8"?> <students> <student id="20110806100"> <name>小明</name> <age>22</age> <sex>男</sex> </student> <student id="20110806101"> <name>小李</name> <age>24</age> <sex>男</sex> </student> <student id="20110806102"> <name>小丽</name> <age>21</age> <sex>女</sex> </student> </students>
[2] 根据XML文件中的节点目录,创建一个相对应的实体类,来保存解析的相应信息。在包:com.andyidea.entity下新建Student.java类。
package com.andyidea.entity; public class Student { private String id; private String name; private int age; private String sex; public String getId() { return id; } public void setId(String 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 getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } }
[3] 定义一个使用PULL解析XML文件的工具类:ParserByPULL.java。
package com.andyidea.util; import java.io.InputStream; import java.util.ArrayList; import java.util.List; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserFactory; import android.util.Xml; import com.andyidea.entity.Student; public class ParserByPULL { //采用XmlPullParser来解析XML文件 public static List<Student> getStudents(InputStream inStream) throws Throwable { List<Student> students = null; Student mStudent = null; //========创建XmlPullParser,有两种方式======= //方式一:使用工厂类XmlPullParserFactory XmlPullParserFactory pullFactory = XmlPullParserFactory.newInstance(); XmlPullParser parser = pullFactory.newPullParser(); //方式二:使用Android提供的实用工具类android.util.Xml //XmlPullParser parser = Xml.newPullParser(); //解析文件输入流 parser.setInput(inStream, "UTF-8"); //产生第一个事件 int eventType = parser.getEventType(); //只要不是文档结束事件,就一直循环 while(eventType!=XmlPullParser.END_DOCUMENT) { switch (eventType) { //触发开始文档事件 case XmlPullParser.START_DOCUMENT: students = new ArrayList<Student>(); break; //触发开始元素事件 case XmlPullParser.START_TAG: //获取解析器当前指向的元素的名称 String name = parser.getName(); if("student".equals(name)) { //通过解析器获取id的元素值,并设置student的id mStudent = new Student(); mStudent.setId(parser.getAttributeValue(0)); } if(mStudent!=null) { if("name".equals(name)) { //获取解析器当前指向元素的下一个文本节点的值 mStudent.setName(parser.nextText()); } if("age".equals(name)) { //获取解析器当前指向元素的下一个文本节点的值 mStudent.setAge(new Short(parser.nextText())); } if("sex".equals(name)) { //获取解析器当前指向元素的下一个文本节点的值 mStudent.setSex(parser.nextText()); } } break; //触发结束元素事件 case XmlPullParser.END_TAG: // if("student".equals(parser.getName())) { students.add(mStudent); mStudent = null; } break; default: break; } eventType = parser.next(); } return students; } }
[4] 该Demo的入口类:MainActivity.java
package com.andyidea.xmlparser; import java.io.InputStream; import java.util.List; import com.andyidea.entity.Student; import com.andyidea.util.ParserByPULL; import android.app.Activity; import android.content.res.AssetManager; import android.os.Bundle; import android.util.Log; public class MainActivity extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); AssetManager asset = getAssets(); try { InputStream input = asset.open("student.xml"); List<Student> list = ParserByPULL.getStudents(input); for (Student stu : list) { Log.e("StudentInfo","Person ID: " + stu.getId() + "," + stu.getName() + ", " + stu.getAge() + ", " + stu.getSex()); } } catch (Throwable e) { e.printStackTrace(); } } }
[5]最后我们运行程序看看结果如下: