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的解析類: 

 1 package cn.bgxt.parser;
 2 
 3 import java.io.IOException;
 4 import java.io.InputStream;
 5 import java.util.ArrayList;
 6 import java.util.List;
 7 
 8 import org.xmlpull.v1.XmlPullParser;
 9 import org.xmlpull.v1.XmlPullParserException;
10 import org.xmlpull.v1.XmlPullParserFactory;
11 
12 import cn.pull.domain.Person;
13 
14 public class PullXMLTools {
15 
16     public PullXMLTools() {
17         // TODO Auto-generated constructor stub
18     }
19 
20     /**
21      * 把服務器傳遞過的XML流數據解析成對象 
22      * @param inputStream  XML流
23      * @param encode  編碼格式
24      * @return
25      */
26     public static List<Person> parserXML(InputStream inputStream, String encode)
27             throws XmlPullParserException, IOException {
28         List<Person> list = null;
29         Person person = null;
30         //獲得一個XMLPULL工廠類的實例
31         XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
32         //獲得一個XML解析器的實例
33         XmlPullParser parser = factory.newPullParser();
34         //設置解析器的輸入,使用inputStream流式數據。
35         parser.setInput(inputStream, encode);
36         //判斷當前的事件類型
37         int eventType = parser.getEventType();
38         //循環讀取,知道事件類型為文檔結束
39         while (eventType != XmlPullParser.END_DOCUMENT) {
40             switch (eventType) {
41             // 通過判斷事件類型來選擇執行不同的代碼
42             case XmlPullParser.START_DOCUMENT:
43                 //文檔開始的時候,實例化list對象,用於存放XML解析后的數據
44                 list=new ArrayList<Person>();                
45                 break;
46             case XmlPullParser.START_TAG:
47                 //讀取標簽的時候觸發這個事件
48                 if(parser.getName().equals("person"))
49                 {
50                     //如果當前讀取到的節點是person節點,那么實例化一個person對象。
51                     person=new Person();
52                     //獲得person節點中的屬性ID
53                     int id=Integer.parseInt(parser.getAttributeValue(0));
54                     person.setId(id);
55                 }
56                 else if(parser.getName().equals("name"))
57                 {
58                     if(person!=null)
59                     {
60                         //獲得name節點的下一個element Text
61                         String name=parser.nextText();
62                         person.setName(name);
63                     }
64                 }
65                 else if(parser.getName().equals("age"))
66                 {
67                     if(person!=null)
68                     {
69                         //獲得age節點的下一個element Text
70                         int age=Integer.parseInt(parser.nextText());
71                         person.setAge(age);
72                     }
73                 }
74                 break;
75             case XmlPullParser.END_TAG:
76                 if(parser.getName().equals("person"))
77                 {
78                     //讀到結束節點標簽,如果為person,則把之前讀取到的person對象加入list中,
79                     //並且制空person對象。
80                     list.add(person);
81                     person=null;
82                 }
83                 break;
84             }
85             //讀取
86             eventType=parser.next();
87         }
88         return list;
89     }
90 
91 }

  Activity中的代碼,需要實現一個按鈕的點擊事件,因為是在Android4.0+的環境下,需要使用多線程訪問網絡。

 1 package cn.bgxt.xmlforpull;
 2 
 3 import java.io.InputStream;
 4 import java.util.List;
 5 import cn.bgxt.Http.HttpUtils;
 6 import cn.bgxt.parser.PullXMLTools;
 7 import cn.pull.domain.Person;
 8 import android.os.Bundle;
 9 import android.app.Activity;
10 import android.view.Menu;
11 import android.view.View;
12 import android.widget.Button;
13 
14 public class MainActivity extends Activity {
15 
16     private Button btn;
17     
18     @Override
19     protected void onCreate(Bundle savedInstanceState) {
20         super.onCreate(savedInstanceState);
21         setContentView(R.layout.activity_main);
22         
23         btn=(Button)findViewById(R.id.btn);
24         
25         btn.setOnClickListener(new View.OnClickListener() {
26             
27             @Override
28             public void onClick(View v) {
29                 // TODO Auto-generated method stub
30                 Thread thread=new Thread(new Runnable() {                    
31                     @Override
32                     public void run() {
33                         String path="http://192.168.1.107:1231/persons.xml";
34                         InputStream inputStream=HttpUtils.getXML(path);
35                         List<Person> list=null;
36                         try {
37                             list = PullXMLTools.parserXML(inputStream, "utf-8");
38                             for(Person person:list)
39                             {
40                                 System.out.println(person.toString());
41                             }
42                         } catch (Exception e) {
43                             // TODO: handle exception
44                         }
45                         
46                     }
47                 });
48                 thread.start();
49             }
50         });        
51     }
52 
53 }

 

  在設備上運行程序,如果讀取成功,可以在LogCat中查看到輸出內容。

  提供一下示例程序的源碼,有需要的朋友可以下載觀看:http://download.csdn.net/detail/plokmju88/5640375

總結

  現在已經說了兩種在Android平台下解析XML的方式,分別是SAX和PULL,這兩種方式都適用於Android平台,因為都是以流的形式訪問數據,消耗的硬件資源小,速度快,但是也存在不同的適用環境。如果清楚的知道XML文檔的結構,每一級節點的名稱,那么使用PULL方式可以簡化開發,但是如果不確定XML文檔的結構,那還是使用SAX的方式比較妥當,無需關心各節點的名稱。

  請支持原創,尊重原創,轉載請注明出處。謝謝。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM