1. 程式人生 > >_043_Android_解析XML之PULL

_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的方式比較妥當,無需關心各節點的名稱。