android 如何使用SAX解析XML
今天,簡單講講android如何使用SAX解析XML 。
昨天,我看代碼時,看到了解析xml文檔的代碼,是使用SAX解析XML。但是我卻不會使用SAX,于是在網上查找資料,最終解決了問題。這里記錄一下。
解析XML的方式有很多種,大家比較熟悉的可能就是DOM解析。
DOM(文件對象模型)解析:解析器讀入整個文檔,然后構建一個駐留內存的樹結構,然后代碼就可以根據DOM接口來操作這個樹結構了。
優點:整個文檔讀入內存,方便操作:支持修改、刪除和重現排列等多種功能。
缺點:將整個文檔讀入內存中,保留了過多的不需要的節點,浪費內存和空間。
使用場合:一旦讀入文檔,還需要多次對文檔進行操作,并且在硬件資源充足的情況下(內存,CPU)。
為了解決DOM解析存在的問題,就出現了SAX解析。其特點為:
優點:不用實現調入整個文檔,占用資源少。尤其在嵌入式環境中,如android,極力推薦使用SAX解析。
缺點:不像DOM解析一樣將文檔長期駐留在內存中,數據不是持久的。如果事件過后沒有保存數據,數據就會丟失。
使用場合:機器有性能限制。
SAX(Simple API for XML)解析器是一種基于事件的解析器,事件驅動的流式解析方式是,從文件的開始順序解析到文檔的結束,不可暫停或倒退。它的核心是事件處理模式,主要是圍繞著事件源以及事件處理器來工作的。當事件源產生事件后,調用事件處理器相應的處理方法,一個事件就可以得到處理。在事件源調用事件處理器中特定方法的時候,還要傳遞給事件處理器相應事件的狀態信息,這樣事件處理器才能夠根據提供的事件信息來決定自己的行為。
SAX的工作原理:簡單地說就是對文檔進行順序掃描,當掃描到文檔(document)開始與結束、元素(element)開始與結束、文檔(document)結束等地方時通知事件處理函數,由事件處理函數做相應動作,然后繼續同樣的掃描,直至文檔結束。
在SAX接口中,事件源是org.xml.sax包中的XMLReader,他通過parse()方法開始解析XML文檔,并根據文檔內容產生事件。而事件處理器則是org.xml.sax包中的ContentHandler、DTDHandler、ErrorHandler,以及EntityResolver這四個接口。他們分別處理事件源在解析過程中產生不同類的事件(其中DTDHandler為解析文檔DTD時所用)。詳細介紹如下表:
在上述四個接口中,最重要的就是ContentHandler這個接口,下面是對這個接口方法的說明:
//設置一個可以定位文檔內容事件發生位置的定位器對象public void setDocumentLocator(Locator locator)//用于處理文檔解析開始事件public void startDocument()throws SAXException//處理元素開始事件,從參數中可以獲得元素所在名稱空間的uri,元素名稱,屬性類表等信息public void startElement(String namespacesURI , String localName , String qName , Attributes atts) throws SAXException//處理元素結束事件,從參數中可以獲得元素所在名稱空間的uri,元素名稱等信息public void endElement(String namespacesURI , String localName , String qName) throws SAXException//處理元素的字符內容,從參數中可以獲得內容public void characters(char[] ch , int start , int length) throws SAXException這里再介紹下XMLReader中的方法。
//注冊處理XML文檔解析事件ContentHandler public void setContentHandler(ContentHandler handler)//開始解析一個XML文檔 public void parse(InputSorce input) throws SAXExceptionSAX實現實體解析的步驟:
在android中使用SAX是有跡可循的,完全可以按照下面的方法就可以輕松找到xml里的tag,然后得到想要的內容。具體實現步驟如下:
(一)第一步:新建一個工廠類SAXParserFactory,代碼如下:
SAXParserFactory factory = SAXParserFactory.newInstance();(二)第二步:讓工廠類產生一個SAX的解析類SAXParser,代碼如下:
SAXParser parser = factory.newSAXParser();(三)第三步:從SAXPsrser中得到一個XMLReader實例,代碼如下:
XMLReader reader = parser.getXMLReader();(四)第四步:把自己寫的handler注冊到XMLReader中,一般最重要的就是ContentHandler,代碼如下:
RSSHandler handler = new RSSHandler(); reader.setContentHandler(handler);(五)第五步:將一個xml文檔或者資源變成一個java可以處理的InputStream流后,解析正式開始,代碼如下:
parser.parse(is);上面幾個步驟中,最重要、最關鍵的就是第四步,handler的實現。
接下來舉一個簡單的例子:
(1)首先我們拷貝一個beauties.xml文件到assets目錄下,其內容如下:
<?xml version="1.0" encoding="UTF-8"?> <beauties> <beauty> <name>范冰冰</name> <age>28</age> </beauty> <beauty> <name>楊冪</name> <age>23</age> </beauty> </beauties>(2) 然后在layout下面新建一個布局文件saxtest.xml,其內容如下:
(3)在src目錄下新建一個與xml里面的節點對應的一個類Beauty,內容如下:
package com.saxtest;public class Beauty {private String name;private String age;public String getName() {return name;}public void setName(String name) {this.name = name;}public String getAge() {return age;}public void setAge(String age) {this.age = age;}@Overridepublic String toString() {return "美女資料 [年齡=" + age + ", 姓名=" + name + "]";} }再寫一個關鍵的類MySaxHandler,在這個類中我們將解析出來的字符串生成了Beauty對象,并加入到List中,代碼已經詳細注釋,內容如下:
第三個源文件就是SaxTestActivity,這個Activity的布局文件saxtest.xml,之前已經給出過它的內容,現在我們貼出Activity源碼的內容,代碼都已經詳細注釋了:
package com.saxtest;import java.io.InputStream; import java.util.ArrayList;import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory;import org.xml.sax.InputSource; import org.xml.sax.XMLReader;import android.app.Activity; import android.content.res.AssetManager; import android.os.Bundle; import android.widget.TextView;import com.example.saxtest.R;public class SaxTestActivity extends Activity{//聲明裝載Beauty對象的Listprivate ArrayList<Beauty> beautyList;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.saxtest);//初始化beautyList鏈表if(beautyList == null){beautyList = new ArrayList<Beauty>();}doMyMission();setupViews();}/*** 使用SAX解析器解析XML文件的方法*/private void doMyMission(){try {//獲取AssetManager管理器對象AssetManager as = this.getAssets();//通過AssetManager的open方法獲取到beauties.xml文件的輸入流InputStream is = as.open("beauties.xml");//通過獲取到的InputStream來得到InputSource實例InputSource is2 = new InputSource(is);//使用工廠方法初始化SAXParserFactory變量spfSAXParserFactory spf = SAXParserFactory.newInstance();//通過SAXParserFactory得到SAXParser的實例SAXParser sp = spf.newSAXParser();//通過SAXParser得到XMLReader的實例XMLReader xr = sp.getXMLReader();//初始化自定義的類MySaxHandler的變量msh,將beautyList傳遞給它,以便裝載數據MySaxHandler msh = new MySaxHandler(beautyList);//將對象msh傳遞給xrxr.setContentHandler(msh);//調用xr的parse方法解析輸入流xr.parse(is2);} catch (Exception e) {e.printStackTrace();}}/*** 將解析結果輸出到界面的方法*/private void setupViews(){String result = "";for (Beauty b : beautyList) { result += b.toString(); } TextView textView = (TextView) findViewById(R.id.textView); textView.setText(result); }}
右鍵運行工程代碼,結果截圖如下:
簡單講講,使用SAX解析XML 首先需要將xml字符轉成InputSource輸入流,然后通過下面代碼獲取一個XMLReader。
//使用工廠方法初始化SAXParserFactory變量spf
???SAXParserFactory spf = SAXParserFactory.newInstance();
???//通過SAXParserFactory得到SAXParser的實例
???SAXParser sp = spf.newSAXParser();
???//通過SAXParser得到XMLReader的實例
???XMLReader xr = sp.getXMLReader();
然后通過xr.setContentHandler(msh);設置XMLReader解析時的監聽Handler。最后調用XMLReader的parse方法解析輸入流。
在MySaxHandler需要繼承DefaultHandler,然后更加需要在回回調函數里做自己的邏輯。回調函數直接說了,這里在寫一下:
ContentHandler接口的方法有以下幾種: void startDocument();//文檔解析開始時執行 void endDocument();//文檔解析結束時執行 void startElement(String uri, String localName, String qName, Attributes atts);//標簽開始解析時執行 void endElement(String uri, String localName, String qName, Attributes atts);//標簽解析結束時執行 void characters(char[] ch, int start, int length );//解析標簽屬性時執行
這樣可以將解析的數組保存到自己的實體類里。具體可以看看舉的例子。其實很簡單。不過這里還介紹另一種函數解析XML 。
public static RESPONSESTATUS parseResponse(String xml){RESPONSESTATUS response = null; SAXReader reader = new SAXReader(); try {Element root = reader.read(HttpUtils.str2Is(xml)).getRootElement(); if("ResponseStatus".equals(root.getName())){response = new RESPONSESTATUS(); Iterator<Element> it = root.elementIterator(); while(it.hasNext()){Element node = it.next(); if("requestURL".equals(node.getName())){response.requestURL = node.getText(); }else if("statusCode".equals(node.getName())){response.statusCode = node.getText(); }}}} catch (DocumentException e) {e.printStackTrace(); }return response; }
這里其實可能和dom解析一樣,都是直接使用XMLReader直接read整個xml數據,然后逐層變量每個節點,和json解析類似。這樣就不需要設置監聽。
android 如何使用SAX解析XML 就講完了。
就這么簡單。
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的android 如何使用SAX解析XML的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: android StringBuilde
- 下一篇: android http协议添加Auth