Android中的xml解析

一、緒論

? ? ? ? 上周工作需要了解項目的一些大體內(nèi)容,結果在xml解析這一塊看的迷迷糊糊的,所以在這里把學習到xml解析的一些知識記錄一下。

二、分析 ? ?

? ? ? ? android中的xml解析器主要有三種,DOM解析器、SAX解析器和pull解析器。

1、DOM解析器

? ? ? ? DOM(Document Object Model) 是一種用于XML文檔的對象模型,可用于直接訪問XML文檔的各個部分。它是一次性全部將內(nèi)容加載在內(nèi)存中,生成一個樹狀結構,它沒有涉及回調(diào)和復雜的狀態(tài)管理。 缺點是加載大文檔時效率低下,所以一般在解析大文檔時不建議使用DOM解析。

? ? 分析該結構通常需要加載整個文檔和構造樹形結構,然后才可以檢索和更新節(jié)點信息。Android完全支持DOM 解析。利用DOM中的對象,可以對XML文檔進行讀取、搜索、修改、添加和刪除等操作。

? ? ? ? DOM的工作原理:使用DOM對XML文件進行操作時,首先要解析文件,將文件分為獨立的元素、屬性和注釋等,然后以節(jié)點樹的形式在內(nèi)存中對XML文件進行表示,就可以通過節(jié)點樹訪問文檔的內(nèi)容,并根據(jù)需要修改文檔。

? ? ? ? 常用的DOM的接口和類:

Document:該接口定義分析并創(chuàng)建DOM文檔的一系列方法,它是文檔樹的根,是操作DOM的基礎。

Node:該接口提供處理并獲取節(jié)點和子節(jié)點值的方法。

Element:該接口繼承Node接口,提供了獲取、修改XML元素名字和屬性的方法。

NodeList:提供獲得節(jié)點個數(shù)和當前節(jié)點的方法。這樣就可以迭代地訪問各個節(jié)點。

DOMParser:該類是Apache的Xerces中的DOM解析器類,可直接解析XML文件。


2、SAX解析

? ? ? ? SAX(Simple API for XML) 使用流式處理的方式,它并不記錄所讀內(nèi)容的相關信息。它是一種以事件為驅動的XML API,解析速度快,占用內(nèi)存少。使用回調(diào)函數(shù)來實現(xiàn)。 缺點是因為以事件為驅動的它不能回退。

? ? ? ? 它的核心是事件處理模式,主要是圍繞著事件源以及事件處理器來工作的。當事件源產(chǎn)生事件后,調(diào)用事件處理器相應的處理方法,一個事件就可以得到處理。在事件源調(diào)用事件處理器中特定方法的時候,還要傳遞給事件處理器相應事件的狀態(tài)信息,這樣事件處理器才能夠根據(jù)提供的事件信息來決定自己的行為。

? ? ? ? SAX的工作原理:SAX會順序掃描文檔,在掃描到文檔(document)開始與結束、元素(element)開始與結束、元素內(nèi)容(characters)等時通知事件處理方法,事件處理方法進行相應處理,然后繼續(xù)掃描,指導文檔掃描結束。

? ? ? ? 常用的SAX接口和類:

Attrbutes:用于得到屬性的個數(shù)、名字和值。

ContentHandler:定義與文檔本身關聯(lián)的事件(例如,開始和結束標記)。大多數(shù)應用程序都注冊這些事件。

DTDHandler:定義與DTD關聯(lián)的事件。它沒有定義足夠的事件來完整地報告DTD。如果需要對DTD進行語法分析,請使用可選的DeclHandler。

DeclHandler是SAX的擴展。不是所有的語法分析器都支持它。

EntityResolver:定義與裝入實體關聯(lián)的事件。只有少數(shù)幾個應用程序注冊這些事件。

ErrorHandler:定義錯誤事件。許多應用程序注冊這些事件以便用它們自己的方式報錯。

DefaultHandler:它提供了這些接LI的缺省實現(xiàn)。在大多數(shù)情況下,為應用程序擴展DefaultHandler并覆蓋相關的方法要比直接實現(xiàn)一個接口更容易。

? ? ? ? ?下面是部分說明:

SAX處理器說明

部分常用方法說明

? ? ? ? 所以,我們通常要使用XmlReader和DefaultHandler配合起來解析xml文檔。

? ? ? ? SAX的解析流程:

startDocument --> startElement --> characters --> endElement --> endDocument


3、pull解析

? ? ? ? Pull內(nèi)置于Android系統(tǒng)中。也是官方解析布局文件所使用的方式。Pull與SAX有點類似,都提供了類似的事件,如開始元素和結束元素。不同的是,SAX的事件驅動是回調(diào)相應方法,需要提供回調(diào)的方法,而后在SAX內(nèi)部自動調(diào)用相應的方法。而Pull解析器并沒有強制要求提供觸發(fā)的方法。因為他觸發(fā)的事件不是一個方法,而是一個數(shù)字。它使用方便,效率高。Android官方推薦開發(fā)者們使用Pull解析技術。Pull解析技術是第三方開發(fā)的開源技術,它同樣可以應用于JavaSE開發(fā)。

? ? ? ? pull返回的常量:

讀取到xml的聲明返回 START_DOCUMENT;

讀取到xml的結束返回 END_DOCUMENT ;

讀取到xml的開始標簽返回 START_TAG;

讀取到xml的結束標簽返回 END_TAG;

讀取到xml的文本返回 TEXT;

? ? ? ? pull的工作原理:pull提供了開始元素和結束元素。當某個元素開始時,我們可以調(diào)用parser.nextText從XML文檔中提取所有字符數(shù)據(jù)。當解釋到一個文檔結束時,自動生成EndDocument事件。

? ? ? ? 常用的XML pull的接口和類:

XmlPullParser:XML pull解析器是一個在XMLPULL VlAP1中提供了定義解析功能的接口。

XmlSerializer:它是一個接口,定義了XML信息集的序列。

XmlPullParserFactory:這個類用于在XMPULL V1 API中創(chuàng)建XML Pull解析器。

XmlPullParserException:拋出單一的XML pull解析器相關的錯誤。

? ? ? ? pull的解析流程:

start_document --> end_document --> start_tag -->end_tag


在Android中還有第四種方式:android.util.Xml類?(本人未使用過)

? ? ? ? 在Android API中,另外提供了Android.util.Xml類,同樣可以解析XML文件,使用方法類似SAX,也都需編寫Handler來處理XML的解析,但是在使用上卻比SAX來得簡單 ,如下所示:

? ? ? ? 以android.util.XML實現(xiàn)XML解析 :

MyHandler myHandler=new MyHandler0;

android.util.Xm1.parse(url.openC0nnection().getlnputStream(),Xml.Encoding.UTF-8,myHandler);


三、實踐

? ? ? ? 1、首先建立一個參考xml文檔 ?(放在了assets目錄中)


<?xml version="1.0" encoding="utf-8"?>

<rivers>

? ? <river name="靈渠"length="605">

? ? ? ? <introduction>

? ? ? ? ? ? ? ? ? ? ? ? ? 靈渠在廣西壯族自治區(qū)興安縣境內(nèi),是世界上最古老的運河之一,有著“世界古代水利建筑明珠”的美譽。靈渠古稱秦鑿渠、零渠、陡河、興安運河,于公元前214年鑿成通航,距今已2217年,仍然發(fā)揮著功用。

? ? ? ? ? </introduction>

? ? ? ? ? <imageurl>

? ? ? ? ? ? ? ? ? ? ?http://imgsrc.baidu.com/baike/pic/item/389aa8fdb7b8322e08244d3c.jpg

? ? ? ? ? </imageurl>?

? ? </river>

? ? <river name="膠萊運河"length="200">

? ? ? ? ? ?<introduction>

? ? ? ? ? ? ? ? ? ? ? ? ? ?膠萊運河南起黃海靈山海口,北抵渤海三山島,流經(jīng)現(xiàn)膠南、膠州、平度、高密、昌邑和萊州等,全長200公里,流域面積達5400平方公里,南北貫穿山東半島,溝通黃渤兩海。膠萊運河自平度姚家村東的分水嶺南北分流。南流由麻灣口入膠州灣,為南膠萊河,長30公里。北流由海倉口入萊州灣,為北膠萊河,長100余公里。

? ? ? ? ? ? </introduction>

? ? ? ? ? ? <imageurl>

? ? ? ? ? ? ? ? ? ? ? ? ? ? http://imgsrc.baidu.com/baike/pic/item/389aa8fdb7b8322e08244d3c.jpg

? ? ? ? ? ? ?</imageurl>

? ? </river>

? ? <river name="蘇北灌溉總渠"length="168">

? ? ? ? ? ? ? ?<introduction>

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 位于淮河下游江蘇省北部,西起洪澤湖邊的高良澗,流經(jīng)洪澤,青浦、淮安,阜寧、射陽,濱海等六縣(區(qū)),東至扁擔港口入海的大型人工河道。全長168km。

? ? ? ? ? ? ? ? </introduction>

? ? ? ? ? ? ? ? <imageurl>

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? http://imgsrc.baidu.com/baike/pic/item/389aa8fdb7b8322e08244d3c.jpg

? ? ? ? ? ? ? ? ?</imageurl>

? ? ? </river>

</rivers>


我們需要用一個River對象來保存數(shù)據(jù),方便觀察節(jié)點信息,抽象出River類

public class River {

String name;// 名稱

Integer length;// 長度

String introduction;// 介紹

String Imageurl;// 圖片url

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public Integer getLength() {

return length;

}

public void setLength(Integer length) {

this.length = length;

}

public String getIntroduction() {

return introduction;

}

public void setIntroduction(String introduction) {

this.introduction = introduction;

}

public String getImageurl() {

return Imageurl;

}

public void setImageurl(String imageurl) {

Imageurl = imageurl;

}

@Override

public String toString() {

return "River [name=" + name + ", length=" + length + ", introduction="

+ introduction + ", Imageurl=" + Imageurl + "]";

}

}


采用DOM解析時具體處理步驟是:

1?首先利用DocumentBuilderFactory創(chuàng)建一個DocumentBuilderFactory實例

2?然后利用DocumentBuilderFactory創(chuàng)建DocumentBuilder

3?然后加載XML文檔(Document),

4?然后獲取文檔的根結點(Element),

5?然后獲取根結點中所有子節(jié)點的列表(NodeList),

6?然后使用再獲取子節(jié)點列表中的需要讀取的結點。


下面我們就開始讀取xml文檔對象,并添加進List中:

代碼如下: 我們這里是使用assets中的river.xml文件,那么就需要讀取這個xml文件,返回輸入流。 讀取方法為:inputStream=this.context.getResources().getAssets().open(fileName); 參數(shù)是xml文件路徑,當然默認的是assets目錄為根目錄。

然后可以用DocumentBuilder對象的parse方法解析輸入流,并返回document對象,然后再遍歷doument對象的節(jié)點屬性。


/**? ? * DOM解析xml方法? ??

?* @param filePath? ??

?* @return? ??

?*/? ??

private ListDOMfromXML(String filePath) {? ? ? ??

ArrayListlist = new ArrayList();

DocumentBuilderFactory factory = null;

DocumentBuilder builder = null;

Document document = null;

InputStream inputStream = null;

//構建解析器

factory = DocumentBuilderFactory.newInstance();

try {

builder = factory.newDocumentBuilder();

//找到xml文件并且加載

inputStream = this.getResources().getAssets().open(filePath);//getAssets后默認根目錄為assets

document = builder.parse(inputStream);

//找到根Element

Element root=document.getDocumentElement();

NodeList nodes=root.getElementsByTagName(RIVER);

//遍歷根節(jié)點所有子節(jié)點,rivers 下所有river

River river = null;

for (int i = 0; i < nodes.getLength(); i++) {

river = new River();

//獲取river元素節(jié)點

Element riverElement = (Element) nodes.item(i);

//設置river中name和length屬性值

river.setName(riverElement.getAttribute("name"));

river.setLength(Integer.parseInt(riverElement.getAttribute("length")));

//獲取子標簽

Element introduction = (Element) riverElement.getElementsByTagName(INTRODUCTION).item(0);

Element imageurl = (Element) riverElement.getElementsByTagName(IMAGEURL).item(0);

//設置introduction和imageurl屬性

river.setIntroduction(introduction.getFirstChild().getNodeValue());

river.setImageurl(imageurl.getFirstChild().getNodeValue());

list.add(river);

}

} catch (ParserConfigurationException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} catch (SAXException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

for (River river : list) {

Log.w("DOM Test", river.toString());

}

return list;

}

在這里添加到List中, 然后我們使用log將他們打印出來。如圖所示:

XML解析結果

采用SAX解析時具體處理步驟是:

1 創(chuàng)建SAXParserFactory對象

2 根據(jù)SAXParserFactory.newSAXParser()方法返回一個SAXParser解析器

3?根據(jù)SAXParser解析器獲取事件源對象XMLReader

4 實例化一個DefaultHandler對象

5 連接事件源對象XMLReader到事件處理類DefaultHandler中

6 調(diào)用XMLReader的parse方法從輸入源中獲取到的xml數(shù)據(jù)

7 通過DefaultHandler返回我們需要的數(shù)據(jù)集合。

代碼如下:


/**? ??

?* SAX解析xml? ??

?* @param filePath? ??

?* @return? ??

?*/? ??

private ListSAXfromXML(String filePath) {? ? ? ??

ArrayListlist = new ArrayList();

//構建解析器

SAXParserFactory factory = SAXParserFactory.newInstance();

SAXParser parser = null;

XMLReader xReader = null;

try {

parser = factory.newSAXParser();

//獲取數(shù)據(jù)源

xReader = parser.getXMLReader();

//設置處理器

RiverHandler handler = new RiverHandler();

xReader.setContentHandler(handler);

//解析xml文件

xReader.parse(new InputSource(this.getAssets().open(filePath)));

list = handler.getList();

} catch (ParserConfigurationException e) {

e.printStackTrace();

} catch (SAXException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

}

for (River river : list) {

Log.w("DOM Test", river.toString());

}

return list;

}

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,237評論 6 537
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,957評論 3 423
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,248評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,356評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,081評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,485評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,534評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,720評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,263評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 41,025評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,204評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,787評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,461評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,874評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,105評論 1 289
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,945評論 3 395
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,205評論 2 375

推薦閱讀更多精彩內(nèi)容