目錄
SAX(Simple API XML)
DOM(Document Object Model)
Pull ------?谷歌官方推薦
DOM方式最直觀和容易理解催式,但是只適合XML文檔較小的時候使用昵慌,而SAX方式更適合在移動終端系統(tǒng)中使用,因為相比DOM占用內(nèi)存少,適合處理比較大的XML文檔鹉梨,最后的Pull方式使用場合和SAX類似,但是更適合需要提前結(jié)束XML文檔解析的場合。
SAX
SAX解析器是一種基于事件的解析器猜憎,事件驅(qū)動的流式解析方式是爬泥,從文件的開始順序解析到文檔的結(jié)束踩官,不可暫陀毕担或倒退。?
優(yōu)點:解析速度快,占用內(nèi)存少莲绰。非常適合在Android移動設(shè)備中使用栅哀。?
缺點:不會記錄標簽的關(guān)系,而要讓你的應用程序自己處理沦偎,這樣就增加了你程序的負擔谈火。?
工作原理:對文檔進行順序掃描,當掃描到文檔(document)開始與結(jié)束革为、元素(element)開始與結(jié)束系任、文檔 (document)結(jié)束等地方時通知事件處理函數(shù)霜旧,由事件處理函數(shù)做相應動作以清,然后繼續(xù)同樣的掃描,直至文檔結(jié)束崎逃。?
public class ContentHandler extends DefaultHandler{
? ? private String nodeName;
? ? private StringBuilder id;
? ? private StringBuilder name;
? ? private StringBuilder version;
? ? private String TAG = "SAX";
? ? //開始解析 XML 文檔? ?
? ? @Override? ?
? ? public void startDocument() throws SAXException {
? ? ? ? id = new StringBuilder();
? ? ? ? name = new StringBuilder();
? ? ? ? version = new StringBuilder();
? ? }
? ? //開始解析結(jié)點? ?
? ?@Override? ?
? ?public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
? ? //localName 記錄當前結(jié)點的名字? ? ? ? nodeName = localName;
? ? }
? ? //開始提取結(jié)點中內(nèi)容? ?
? ?@Override? ?
? ?public void characters(char[] ch, int start, int length) throws SAXException {
? ? ? ? if("id".equals(nodeName))
? ? ? ? ? ? id.append(ch,start,length);
? ? ? ? else if("name".equals(nodeName))
? ? ? ? ? ? name.append(ch,start,length);
? ? ? ? else if("version".equals(nodeName))
? ? ? ? ? ? version.append(ch,start, length);
? ? }
? ? //結(jié)束結(jié)點解析? ?
? ?@Override
? public void endElement(String uri, String localName, String qName) throws SAXException {
? ? ? ? if("app".equals(localName)){
? ? ? ? ? ? //可能包含回車或換行符? ? ? ? ? ? Log.d(TAG, "endElement: id = " + id.toString().trim());
? ? ? ? ? ? Log.d(TAG, "endElement: name = "+ name.toString().trim());
? ? ? ? ? ? Log.d(TAG, "endElement: version = "+ version.toString().trim());
? ? ? ? ? ? //打印結(jié)束后清空掷倔,否則會影響下一次內(nèi)容的讀取? ? ? ? ? ? id.setLength(0);
? ? ? ? ? ? name.setLength(0);
? ? ? ? ? ? version.setLength(0);
? ? ? ? }
? ? }
? ? //結(jié)束XML文檔解析? ?
? ?@Override? ?
? ?public void endDocument() throws SAXException {
? ? }
}
//用SAX方式解析XML
private void paraseXMLWithSAX(String xmlData){
? ? try {
? ? ? ? SAXParserFactory factory = SAXParserFactory.newInstance();
? ? ? ? XMLReader reader = factory.newSAXParser().getXMLReader();
? ? ? ? ContentHandler handler = new ContentHandler();
? ? ? //將contentHandler的實例設(shè)置到XMLReader中? ? ? reader.setContentHandler(handler);
? ? ? //開始解析? ? ? reader.parse(new InputSource(new StringReader(xmlData)));
? }catch(Exception e){
? ? ? ? e.printStackTrace();
? }
}
Pull 方式解析
PULL解析器的運行方式和SAX類似泽裳,都是基于事件的模式苹熏。不同的是,在PULL解析過程中返回的是數(shù)字惰拱,且我們需要自己獲取產(chǎn)生的事件然后做相應的操作巴柿,而不像SAX那樣由處理器觸發(fā)一種事件的方法凛虽,執(zhí)行我們的代碼。?
**解析過程:**XML pull提供了開始元素和結(jié)束元素广恢。當某個元素開始時凯旋,我們可以調(diào)用parser.nextText從XML文檔中提取所有字符數(shù)據(jù)。當解釋到一個文檔結(jié)束時钉迷,自動生成EndDocument事件至非。
讀取到xml的聲明返回 START_DOCUMENT;?
讀取到xml的開始標簽返回 START_TAG?
讀取到xml的文本返回 TEXT?
讀取到xml的結(jié)束標簽返回 END_TAG?
讀取到xml的結(jié)束返回 END_DOCUMENT
優(yōu)點:?PULL解析器小巧輕便,解析速度快糠聪,簡單易用睡蟋,非常適合在Android移動設(shè)備中使用,Android系統(tǒng)內(nèi)部在解析各種XML時也是用PULL解析器枷颊,Android官方推薦開發(fā)者們使用Pull解析技術(shù)戳杀。Pull解析技術(shù)是第三方開發(fā)的開源技術(shù),它同樣可以應用于JavaSE開發(fā)夭苗。
//用Pull方式解析XML
private void parseXMLWithPull(String xmlData){
? try {
? ? XmlPullParserFactory? factory = XmlPullParserFactory.newInstance();
? ? XmlPullParser xmlPullParser = factory.newPullParser();
? ? //設(shè)置輸入的內(nèi)容? ? xmlPullParser.setInput(new StringReader(xmlData));
? ? //獲取當前解析事件信卡,返回的是數(shù)字? ? int eventType = xmlPullParser.getEventType();
? ? //保存內(nèi)容? ? String id = "";
? ? String name = "";
? ? String version="";
? ? while (eventType != (XmlPullParser.END_DOCUMENT)){
? ? ? ? ? String nodeName = xmlPullParser.getName();
? ? ? ? ? switch (eventType){
? ? ? ? ? //開始解析XML? ? ? ? ? case XmlPullParser.START_TAG:{
? ? ? ? ? ? ? //nextText()用于獲取結(jié)點內(nèi)的具體內(nèi)容? ? ? ? ? ? ? if("id".equals(nodeName))
? ? ? ? ? ? ? ? ? id = xmlPullParser.nextText();
? ? ? ? ? ? ? else if("name".equals(nodeName))
? ? ? ? ? ? ? ? ? name = xmlPullParser.nextText();
? ? ? ? ? ? ? ? else if("version".equals(nodeName))
? ? ? ? ? ? ? ? ? version = xmlPullParser.nextText();
? ? ? ? ? ? } break;
? ? ? ? ? //結(jié)束解析? ? ? ? ? case XmlPullParser.END_TAG:{
? ? ? ? ? ? ? ? if("app".equals(nodeName)){
? ? ? ? ? ? ? ? ? Log.d(TAG, "parseXMLWithPull: id is "+ id);
? ? ? ? ? ? ? ? ? Log.d(TAG, "parseXMLWithPull: name is "+ name);
? ? ? ? ? ? ? ? ? Log.d(TAG, "parseXMLWithPull: version is "+ version);
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? } break;
? ? ? ? ? default: break;
? ? ? ? ? }
? ? ? ? ? //下一個? ? ? ? ? eventType = xmlPullParser.next();
? ? }
? ? } catch (Exception e) {
? ? ? ? e.printStackTrace();
? ? }
}
DOM方式解析
DOM,即對象文檔模型题造,它是將整個XML文檔載入內(nèi)存(所以效率較低傍菇,不推薦使用),每一個節(jié)點當做一個對象界赔,結(jié)合代碼分析丢习。DOM實現(xiàn)時首先為XML文檔的解析定義一組接口牵触,解析器讀入整個文檔,然后構(gòu)造一個駐留內(nèi)存的樹結(jié)構(gòu)咐低,這樣代碼就可以使用DOM接口來操作整個樹結(jié)構(gòu)揽思。 由于DOM在內(nèi)存中以樹形結(jié)構(gòu)存放,因此檢索和更新效率會更高见擦。但是對于特別大的文檔钉汗,解析和加載整個文檔將會很耗資源。 當然鲤屡,如果XML文件的內(nèi)容比較小损痰,采用DOM是可行的。?
工作原理:使用DOM對XML文件進行操作時酒来,首先要解析文件卢未,將文件分為獨立的元素、屬性和注釋等堰汉,然后以節(jié)點樹的形式在內(nèi)存中對XML文件進行表示尝丐,就可以通過節(jié)點樹訪問文檔的內(nèi)容,并根據(jù)需要修改文檔衡奥。
使用步驟:
首先利用DocumentBuilderFactory創(chuàng)建一個DocumentBuilderFactory實例
然后利用DocumentBuilderFactory創(chuàng)建DocumentBuilder
然后加載XML文檔(Document)
然后獲取文檔的根結(jié)點(Element)爹袁,
然后獲取根結(jié)點中所有子節(jié)點的列表(NodeList),
然后使用再獲取子節(jié)點列表中的需要讀取的結(jié)點矮固。