前言
在上一篇博客已經介紹了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的方式比較妥當,無需關心各節點的名稱。
請支持原創,尊重原創,轉載請注明出處。謝謝。