_043_Android_解析XML之PULL
前言
在上一篇部落格已經介紹了Android解析XML的幾種方式,分別有:SAX、DOM、PULL。詳細的可以看看上一篇部落格:http://www.cnblogs.com/plokmju/p/android_XMLForSAX.html。這篇部落格就介紹一下PULL解析XML。
XMLPULL的一些特點:
- 簡單的介面:XMLPULL由一個介面(XmlPullParser)、一個例外(XmlPullParserException)、一個工廠(XmlPullParserFactory)來建立。
- 易用性:只有一個關鍵的next()方法,用於檢索下一事件。
- 易擴充套件:使用通用的介面,並允許多個實現功能,具有更好的擴充套件性。
- 效能:XMLPULL被設計為允許執行速度非常快的XML解析器。
- 記憶體要求低:XMLPULL被設計為相容J2ME,在小型裝置上,解析XML時佔用非常小的記憶體。
關鍵方法next()
對於XMLPULL,只有一個關鍵的next()方法需要了解一下,它是用於檢索下一個事件,並有五個事件,這五個分別是:
- START_DOCUMENT:文件的開始,解析器尚未讀取任何輸入。
- START_TAG:開始標籤的解析。
- TEXT:標籤內元素的內容解析。
- END_TAG:結束標籤的解析。
- END_DOCUMENT:文件的結束。
雖然說關鍵方法只有一個用於檢索下一事件的方法next(),但是還存在一些方法也可以檢索下一事件,用於不同的情況下使用,如:nextText():用於檢索下一元素的文字;nextTag():用於檢索下一元素的標籤。
XMLPULL的簡單步驟
- 需要建立一個XMLPULL解析器物件。通過XmlPullParserFactory物件得到解析器物件XmlPullParser。
- 再使用XmlPullParser.setInput()方法設定解析器的輸入。
- 之後再通過判斷事件型別,迴圈呼叫next()方法獲得解析的資料。
對於XmlPullParserFactory類,沒有提供公開的構造方法(單例模式),必須使用它的靜態方法newInstance()來獲得物件例項。獲得XmlPullParser必須使用XmlPullParserFactory.newPullParser()獲得。
示例
現在通過一個示例程式來講解一下XMLPULL的使用。
這是一個Android應用程式,需要增加訪問網路的許可權,解析IIS伺服器上的一個靜態的.XML檔案。佈局介面也比較簡單,就是一個按鈕,這裡不展示程式碼了,具體的可以下載程式碼檢視。
待解析的XML檔案內容:
<?xml version="1.0" encoding="utf-8"?>
<persons>
<person id="23">
<name >Jack</name>
<age>21</age>
</person>
<person id="20">
<name>Dick</name>
<age>23</age>
</person>
</persons>
IIS伺服器上的XML檔案,使用的HTTPURLConnection的方式獲得,具體參見另外一篇部落格:http://www.cnblogs.com/plokmju/p/java-HTTP.html。這裡就再重複給出。
新建一個Person類,用於存放通過XML解析之後的資料,只有三個欄位id、name、age並提供對於的get()set()方法,還有toString()方法,這裡不展示程式碼了。
以下是PullXML的解析類:
package cn.bgxt.parser;
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;
import cn.pull.domain.Person;
public class PullXMLTools {
public PullXMLTools() {
// TODO Auto-generated constructor stub
}
/**
* 把伺服器傳遞過的XML流資料解析成物件
* @param inputStream XML流
* @param encode 編碼格式
* @return
*/
public static List<Person> parserXML(InputStream inputStream, String encode)
throws XmlPullParserException, IOException {
List<Person> list = null;
Person person = null;
//獲得一個XMLPULL工廠類的例項
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
//獲得一個XML解析器的例項
XmlPullParser parser = factory.newPullParser();
//設定解析器的輸入,使用inputStream流式資料。
parser.setInput(inputStream, encode);
//判斷當前的事件型別
int eventType = parser.getEventType();
//迴圈讀取,知道事件型別為文件結束
while (eventType != XmlPullParser.END_DOCUMENT) {
switch (eventType) {
// 通過判斷事件型別來選擇執行不同的程式碼
case XmlPullParser.START_DOCUMENT:
//文件開始的時候,例項化list物件,用於存放XML解析後的資料
list=new ArrayList<Person>();
break;
case XmlPullParser.START_TAG:
//讀取標籤的時候觸發這個事件
if(parser.getName().equals("person"))
{
//如果當前讀取到的節點是person節點,那麼例項化一個person物件。
person=new Person();
//獲得person節點中的屬性ID
int id=Integer.parseInt(parser.getAttributeValue(0));
person.setId(id);
}
else if(parser.getName().equals("name"))
{
if(person!=null)
{
//獲得name節點的下一個element Text
String name=parser.nextText();
person.setName(name);
}
}
else if(parser.getName().equals("age"))
{
if(person!=null)
{
//獲得age節點的下一個element Text
int age=Integer.parseInt(parser.nextText());
person.setAge(age);
}
}
break;
case XmlPullParser.END_TAG:
if(parser.getName().equals("person"))
{
//讀到結束節點標籤,如果為person,則把之前讀取到的person物件加入list中,
//並且制空person物件。
list.add(person);
person=null;
}
break;
}
//讀取
eventType=parser.next();
}
return list;
}
}
官方Demo:
public class Demo {
public static void main(String args[]) throws XmlPullParserException, IOException {
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
factory.setNamespaceAware(true);
XmlPullParser xpp = factory.newPullParser();
xpp.setInput(new StringReader("<foo>Hello World!<h>dfdfdfdf<h>dfdfdfdf</h></h></foo>"));
int eventType = xpp.getEventType();
while (eventType != XmlPullParser.END_DOCUMENT) {
if (eventType == XmlPullParser.START_DOCUMENT) {
System.out.println("Start document");
} else if (eventType == XmlPullParser.START_TAG) {
System.out.println("Start tag " + xpp.getName());
} else if (eventType == XmlPullParser.END_TAG) {
System.out.println("End tag " + xpp.getName());
} else if (eventType == XmlPullParser.TEXT) {
System.out.println("Text " + xpp.getText());
}
eventType = xpp.next();
}
System.out.println("End document");
}
}
總結
現在已經說了兩種在Android平臺下解析XML的方式,分別是SAX和PULL,這兩種方式都適用於Android平臺,因為都是以流的形式訪問資料,消耗的硬體資源小,速度快,但是也存在不同的適用環境。如果清楚的知道XML文件的結構,每一級節點的名稱,那麼使用PULL方式可以簡化開發,但是如果不確定XML文件的結構,那還是使用SAX的方式比較妥當,無需關心各節點的名稱。