Pull和Sax類似,都是基于流(stream)操作檔案,然後根據節點事件回調開發者編寫的處理程式。因為是基于流的處理,是以Pull和Sax都比較節約記憶體資源,不會象Dom那樣要把所有節點以對橡樹的形式展現在記憶體中。 但Pull比Sax更簡明,而且不需要掃描完整個流。
他們的差別為:SAX解析器的工作方式是自動将事件推入注冊的事件處理器進行處理,是以你不能控制事件的處理主動結束;而Pull解析器的工作方式為允許你的應用程式代碼主動從解析器中擷取事件,正因為是主動擷取事件,是以可以在滿足了需要的條件後不再擷取事件,結束解析。這是他們主要的差別。如果在一個XML文檔中我們隻需要前面一部分資料,但是使用SAX方式或DOM方式會對整個文檔進行解析,中間不能終止暫停,盡管XML文檔中後面的大部分資料我們其實都不需要解析,是以這樣實際上就浪費了處理資源。使用PULL方式正合适。
Pull解析器也提供了類似SAX的事件,開始文檔START_DOCUMENT和結束文檔END_DOCUMENT,開始元素START_TAG和結束元素END_TAG,遇到元素内容TEXT等,但需要調用next() 方法提取它們(主動提取事件)。
Android系統中和Pull方式相關的包為org.xmlpull.v1. PULL是個開源的項目,源碼位址http://www.xmlpull.org/
經常需要使用的類:
XmlPullParserFactory 工廠類,用來建立pull解析器
XmlPullParser pull解析器
XmlPullParserException 異常
XmlSerializer 該類用來将指定的對象轉化為XML文檔
建立XmlPullParser
建立XmlPullParser方式有兩種:
方式一:通過XmlPullParserFactory建立
XmlPullParserFactory xpf = XmlPullParserFactory.newInstance();//構造工廠執行個體
XmlPullParser parser = xpf.newPullParser();//建立解析對象
方法二:通過Android.util.Xml類
XmlPullParser parser = Xml.newPullParser();
下面開始用Pull解析
解析的流程如下:
(1)取得pull解析器
(2)設定解析器的輸入流
(3)産生第一個事件
(4)開始解析
(5)解析結束
解析XML檔案如下:
<?xml version="1.0" encoding="utf-8"?>
<rivers>
<river name="靈渠" length="605">
<introduction>
靈渠在廣西壯族自治區興安縣境内,是世界上最古老的運河之一,有着“世界古代水利建築明珠”的美譽。靈渠古稱秦鑿渠、零渠、陡河、興安運河,于公元前214年鑿成通航,距今已2217年,仍然發揮着功用。
</introduction>
<imageurl>
http://www.2cto.com/uploadfile/2012/0228/20120228094142711.jpg
</imageurl>
</river>
<river name="膠萊運河" length="200">
<introduction>
膠萊運河南起黃海靈山海口,北抵渤海三山島,流經現膠南、膠州、平度、高密、昌邑和萊州等,全長200公裡,流域面積達5400平方公裡,南北貫穿山東半島,溝通黃渤兩海。膠萊運河自平度姚家村東的分水嶺南北分流。南流由麻灣口入膠州灣,為南膠萊河,長30公裡。北流由海倉口入萊州灣,為北膠萊河,長100餘公裡。
</introduction>
<imageurl>
http://www.2cto.com/uploadfile/2012/0228/20120228094142711.jpg
</imageurl>
</river>
<river name="蘇北灌溉總渠" length="168">
<introduction>
位于淮河下遊江蘇省北部,西起洪澤湖邊的高良澗,流經洪澤,青浦、淮安,阜甯、射陽,濱海等六縣(區),東至扁擔港口入海的大型人工河道。全長168km。
</introduction>
<imageurl>
http://www.2cto.com/uploadfile/2012/0228/20120228094142711.jpg
</imageurl>
</river>
</rivers>
解析過程:
private List<River> parserXMLPULL(InputStream is)
{
List<River> list = null;
River river = null;
// XmlPullParserException
// XmlSerializer
// 方式一:
// XmlPullParser parser = Xml.newPullParser();
// 方法二:
XmlPullParserFactory xpf = null;
XmlPullParser parser = null;
try {
xpf = XmlPullParserFactory.newInstance();
parser = xpf.newPullParser();
// 将XML檔案以流的形式加入,并設定XML檔案的編碼方式
// parser.setInput(InputStrean inputStream, String inputEncoding)
// parser.setInput(Reader reader)
parser.setInput(is, "UTF-8");
// 此時文檔剛初始化,是以解析的位置在文檔的開頭
int type = parser.getEventType();//此時傳回0,也就是在START_DOCUMENT
// 傳回類型START_DOCUMENT,END_DOCUMENT,START_TAG,END_TAG,TEXT
while(type!= XmlPullParser.END_DOCUMENT)
{
switch(type)
{
case XmlPullParser.START_DOCUMENT:
//做一些初始化工作
list = new ArrayList<River>();
break;
case XmlPullParser.START_TAG:
//rivers
String name = parser.getName();
if(name.equals("river"))
{
String attrName = parser.getAttributeValue(0);
int attrLen = Integer.parseInt(parser.getAttributeValue(1));
river = new River();
river.setName(attrName);
river.setLength(attrLen);
}
if(parser.getName().equals("introduction")&&river!=null)
{
String intro = parser.nextText();
river.setIntro(intro);
}
if("imageurl".equals(parser.getName())&&river!=null)
{
String url = parser.nextText();
river.setUrl(url);
}
break;
case XmlPullParser.END_TAG:
String value = parser.getName();
if(value.equals("river")&&river!=null&&list!=null)
{
// 添加對象到list中
list.add(river);
river = null;
}
break;
}
type = parser.next();//目前解析位置結束,指向下一個位置
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (XmlPullParserException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return list;
}
River 類很簡單
package com.liupan.parse;
public class River {
private String name;
private int length;
private String intro;
private String url;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getLength() {
return length;
}
public void setLength(int length) {
this.length = length;
}
public String getIntro() {
return intro;
}
public void setIntro(String intro) {
this.intro = intro;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
}
XmlSerializer類的使用
public String createXML(Writer writer ,List<River> list) throws Exception
{
XmlSerializer serial =Xml.newSerializer();
//設定輸出流的位置,本句會抛出異常
serial.setOutput(writer);
//以下開始建立XML檔案
serial.startDocument("utf-8", true);//對應之前解析時出現的事件
serial.startTag("", "rivers");
//将list的内容寫入XML檔案
if(list!=null)
{
for(River river : list)
{
//建立river标簽
serial.startTag("", "river");
//為river标簽添加屬性 name 和length
serial.attribute("", "name",river.getName());
serial.attribute("", "length",""+river.getLength());
serial.startTag("", "introduction");
serial.text(river.getIntro());
serial.endTag("", "introduction");
serial.startTag("", "imageurl");
serial.text(river.getUrl());
serial.endTag("", "imageurl");
serial.endTag("","river");
}
}
serial.endTag("", "rivers");
serial.endDocument();
// 重新整理輸出的緩沖區
writer.flush();
//關閉輸出流
writer.close();
return writer.toString();
}