使用PULL方式解析XML:
Pull是STAX的一個實現
StAX是The Streaming API for XML的縮寫,一種利用拉模式解析(pull-parsing)XML文檔的API
StAX通過提供一種基于事件迭代器(Iterator)的API讓程序員去控制xml文檔解析過程。
為什么說StAX方式的效率優于SAX呢?
因為SAX 是推模式的,所有的操作在解析器自動控制下進行,所有事件都會處理,不管需不需要解析整個文檔,解析器都會自動啟動解析任務,然后按順序向下解析,直到解析完成才終止。而StAX 是拉模式的,可以由用戶根據需要控制需要處理事件類型及何時終止解析任務,用戶調用一次next(),解析器就進行一次向下解析,完全在用戶的控制下進行解析操作,在需要的解析工作已經完成時,可以隨時終止解析。
簡單說來,推模式,就是你把如何操作通通告訴解析器,之后,解析器自動去完成所有解析任務,你不能做任何干涉了。
而拉模式就像抽紙,隨用隨拉,需要時就拉一下,不需要時,它不會自動推出來。你可以一直拉把一盒抽紙拉完,也可以按自己需要只拉幾張。
可以從網上下載PULL解析的第三方jar包,來使用PULL解析XML
www.xmlpull.org上有3種PULL的實現可以下載:

由描述信息可以看出,XPP3這種實現主要致力于性能和易于使用,而且,android內置的PULL解析器似乎也是XPP3,所以可以下載這種實現,來實現XML的PULL解析。
選擇合適的XPP3下載:

如,我下載了:

下載完成后,解壓縮,然后找到文件名類似于xpp3-1.1.4c.jar的jar包,這里面就有我們需要的API。
doc目錄中的api目錄中存放著API幫助手冊,可以參考該手冊,學習使用XPP3 PULL解析器。

如同DOM和SAX解析XML一樣,PULL解析XML也要用到解析器工廠類XmlPullParserFactory,解析器類XmlPullParser,XPP3中還提供了XmlSerializer類用于將內存對象實現序列化到xml文檔。

工廠類也是通過靜態方法newInstance()獲得工廠類對象。

newPullParser()和newSerializer()方法分別用于獲取XmlPullParser對象和XmlSerializer對象。
以上就是工廠類的常用的三個方法。
XmlPulParser通過setInput()方法,設置要解析的XML文檔。

通過調用next方法,一步步向下解析

通過調用getEventType()方法,來確認當前解析XML所觸發的事件類型。

事件類型通過XmlPullParser中定義的幾個常量來標識:
START_DOCUMENT:開始解析觸發
START_DOCUMENT:碰到節點時觸發
TEXT:讀取字符文本時觸發
END_TAG:碰到結束節點時觸發
END_DOCUMENT:解析完成時觸發
當觸發事件類型是START_TAG或者END_TAG時,可以通過getName()方法獲取當前節點名稱。

當事件類型是START_TAG時,可以通過nextText()獲取該節點的文本子節點內容,若事件類型為END_TAG則會返回一個空字符串。

當事件類型是START_TAG時,通過getAttributeCount()方法,可以獲取該節點的屬性個數

通過getAttributeName(int index)方法,可以獲取指定index的屬性的名稱

通過getAttributeValue(int index)方法,可以獲取指定index屬性的值。

以上,是XmlPullParser類中的幾個常用方法。
XmlSerializer實現將內存中的數據序列化到XML文檔中,也有幾個常用的方法:
setOutput()方法,指定要將數據序列化到哪個XML文件中

startDocument()方法,指定XML文檔的開始<?xml聲明信息

如:startDocument(“utf-8”, true);將在XML文檔中輸出如下信息:
<?xml encoding="UTF-8" standalone="yes"?>
startTag()開始一個節點,namespace沒有,一般設置為null或者空字符串

text()設置文本內容

endTage()結束一個節點。

attribute()設置節點的屬性。

了解了這幾個類的常用方法后,就可以實現PULL模式的XML解析和序列化了。但是,現在有個問題:DOM可以實現增刪改查操作,PULL模式可以嗎?
由于在DOM模式下,整個文檔對象都在內存中,所以可以實現修改回寫。但是PULL模式以及SAX模式下,都是邊解析邊釋放內存的,不能直接實現增刪改查操作。但是,可以模仿DOM模式,把解析的部分保存在內存中,如把解析的對象都保存到一個List中。然后所有的增刪改查操作,都針對List對象進行,所有操作執行完成之后,再把內存中最終版本的List序列化到Xml文檔中,就間接實現了PULL模式下的增刪改查操作。
具體操作可以參考下面代碼:
待解析的students.xml:
1 <?xml version="1.0" encoding="UTF-8" standalone="no"?> 2 3 <students> 4 5 <student id="000"> 6 7 <name>zhangsan22</name> 8 9 <gender>female</gender>10 11 <age>26</age>12 13 </student>14 15 <student id="002">16 17 <name>lisi</name>18 19 <gender>male</gender>20 21 <age>24</age>22 23 </student>24 25 <student id="003">26 27 <name>xiaoqiao</name>28 29 <gender>female</gender>30 31 <age>18</age>32 33 </student>34 35 <student id="004">36 37 <name>diaochan</name>38 39 <gender>female</gender>40 41 <age>23</age>42 43 </student>44 45 </students>
對應的實體類:Student.java:
1 package cn.csc.bean; 2 3 public class Student { 4 5 PRivate String id = null; 6 7 private String name = null; 8 9 private String gender = null;10 11 private int age = 0;12 13 public String getId() {14 15 return id;16 17 }18 19 public void setId(String id) {20 21 this.id = id;22 23 }24 25 public String getName() {26 27 return name;28 29 }30 31 public void setName(String name) {32 33 this.name = name;34 35 }36 37 public String getGender() {38 39 return gender;40 41 }42 43 public void setGender(String gender) {44 45 this.gender = gender;46 47 }48 49 public int getAge() {50 51 return age;52 53 }54 55 public void setAge(int age) {56 57 this.age = age;58 59 }60 61 public Student(String id, String name, String gender, int age) {62 63 super();64 65 this.id = id;66 67 this.name = name;68 69 this.gender = gender;70 71 this.age = age;72 73 }74 75 public Student() {76 77 super();78 79 }80 81 public String toString() {82 83 return "[id:"+id+",name:"+name+",gender:"+gender+",age"+age+"]";84 85 }86 87 }StudentPullUtils類,實現兩個方法,一個用于將xml文件中的student解析到List<Student>中,一個用于將List<Student>中的數據序列化到指定的xml文件中:
1 public class StudentPullUtils { 2 3 public static List<Student> parseXml(String filename) throws Exception{ 4 5 List<Student> list = new ArrayList<Student>(); 6 7 XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); 8 9 XmlPullParser parser = factory.newPullParser(); 10 11 parser.setInput(new FileInputStream(filename), "utf-8"); 12 13 int eventType; 14 15 Student s = null; 16 17 while((eventType = parser.getEventType())!= XmlPullParser.END_DOCUMENT){ 18 19 if(eventType == XmlPullParser.START_TAG && parser.getName().equals("student")){ 20 21 s = new Student(); 22 23 s.setId(parser.getAttributeValue(0)); 24 25 } 26 27 if(eventType == XmlPullParser.START_TAG && parser.getName().equals("name")){ 28 29 s.setName(parser.nextText()); 30 31 } 32 33 if(eventType == XmlPullParser.START_TAG && parser.getName().equals("age")){ 34 35 s.setAge(Integer.parseInt(parser.nextText())); 36 37 } 38 39 if(eventType == XmlPullParser.START_TAG && parser.getName().equals("gender")){ 40 41 s.setGender(parser.nextText()); 42 43 } 44 45 if(eventType == XmlPullParser.END_TAG && parser.getName().equals("student")){ 46 47 list.add(s); 48 49 } 50 51 parser.next(); 52 53 } 54 55 return list; 56 57 } 58 59 60 61 public static boolean serializeList(List<Student> list, String filename) throws Exception{ 62 63 XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); 64 65 XmlSerializer serializer = factory.newSerializer(); 66 67 serializer.setOutput(new FileOutputStream(filename), "utf-8"); 68 69 serializer.startDocument("utf-8", true); 70 71 serializer.startTag(null, "students"); 72 73 for(Student s : list){ 74 75 serializer.startTag(null, "student"); 76 77 serializer.attribute(null, "id", s.getId()); 78 79 serializer.startTag(null, "name"); 80 81 serializer.text(s.getName()); 82 83 serializer.endTag(null, "name"); 84 85 serializer.startTag(null, "gender"); 86 87 serializer.text(s.getGender()); 88 89 serializer.endTag(null, "gender"); 90 91 serializer.startTag(null, "age"); 92 93 serializer.text(s.getAge()+""); 94 95 serializer.endTag(null, "age"); 96 97 serializer.endTag(null, "student"); 98 99 }100 101 serializer.endTag(null, "students");102 103 serializer.endDocument();104 105 106 107 return true;108 109 }110 111 }調用測試:實現將數據從students.xml中讀取到Lis<Student>中,所有學生的年齡加1,然后序列化到students_bak.xml中:
1 List<Student> list = StudentPullUtils.parseXml("students.xml");2 3 for(Student s: list){4 5 s.setAge(s.getAge()+1);6 7 }8 9 StudentPullUtils.serializeList(list, "students_bak.xml");新聞熱點
疑難解答