android xml解析的三种方式
2019獨角獸企業(yè)重金招聘Python工程師標(biāo)準(zhǔn)>>>
在android開發(fā)中,經(jīng)常用到去解析xml文件,常見的解析xml的方式有一下三種:SAX、Pull、Dom解析方式。最近做了一個android版的CSDN閱讀器,用到了其中的兩種(sax,pull),今天對android解析xml的這三種方式進行一次總結(jié)。
? ? ?今天解析的xml示例(channels.xml)如下:
<?xml version="1.0" encoding="utf-8"?> <channel> <item id="0" url="http://www.baidu.com">百度</item> <item id="1" url="http://www.qq.com">騰訊</item> <item id="2" url="http://www.sina.com.cn">新浪</item> <item id="3" url="http://www.taobao.com">淘寶</item> </channel>?
?一、使用sax方式解析
?基礎(chǔ)知識:
? ? ?這種方式解析是一種基于事件驅(qū)動的api,有兩個部分,解析器和事件處理器,解析器就是XMLReader接口,負(fù)責(zé)讀取XML文檔,和向事件處理器發(fā)送事件(也是事件源),事件處理器ContentHandler接口,負(fù)責(zé)對發(fā)送的事件響應(yīng)和進行XML文檔處理。
? ? ?下面是ContentHandler接口的常用方法
? ? ?public abstract void characters (char[] ch, int start, int length)
? ? ? 這個方法來接收字符塊通知,解析器通過這個方法來報告字符數(shù)據(jù)塊,解析器為了提高解析效率把讀到的所有字符串放到一個字符數(shù)組(ch)中,作為參數(shù)傳遞給character的方法中,如果想獲取本次事件中讀取到的字符數(shù)據(jù),需要使用start和length屬性。
? ??public abstract void startDocument () 接收文檔開始的通知
? ???public abstract void endDocument () 接收文檔結(jié)束的通知
? ??public abstract void startElement (String uri, String localName, String qName, Attributes atts) 接收文檔開始的標(biāo)簽
? ??public abstract void endElement (String uri, String localName, String qName) 接收文檔結(jié)束的標(biāo)簽
? ? 在一般使用中為了簡化開發(fā),在org.xml.sax.helpers提供了一個DefaultHandler類,它實現(xiàn)了ContentHandler的方法,我們只想繼承DefaultHandler方法即可。
? ?另外SAX解析器提供了一個工廠類:SAXParserFactory,SAX的解析類為SAXParser 可以調(diào)用它的parser方法進行解析。
? ?看了些基礎(chǔ)以后開始上代碼吧
1 public class SAXPraserHelper extends DefaultHandler {2 3 final int ITEM = 0x0005;4 5 List<channel> list;6 channel chann;7 int currentState = 0;8 9 public List<channel> getList() { 10 return list; 11 } 12 13 /* 14 * 接口字符塊通知 15 */ 16 @Override 17 public void characters(char[] ch, int start, int length) 18 throws SAXException { 19 // TODO Auto-generated method stub 20 // super.characters(ch, start, length); 21 String theString = String.valueOf(ch, start, length); 22 if (currentState != 0) { 23 chann.setName(theString); 24 currentState = 0; 25 } 26 return; 27 } 28 29 /* 30 * 接收文檔結(jié)束通知 31 */ 32 @Override 33 public void endDocument() throws SAXException { 34 // TODO Auto-generated method stub 35 super.endDocument(); 36 } 37 38 /* 39 * 接收標(biāo)簽結(jié)束通知 40 */ 41 @Override 42 public void endElement(String uri, String localName, String qName) 43 throws SAXException { 44 // TODO Auto-generated method stub 45 if (localName.equals("item")) 46 list.add(chann); 47 } 48 49 /* 50 * 文檔開始通知 51 */ 52 @Override 53 public void startDocument() throws SAXException { 54 // TODO Auto-generated method stub 55 list = new ArrayList<channel>(); 56 } 57 58 /* 59 * 標(biāo)簽開始通知 60 */ 61 @Override 62 public void startElement(String uri, String localName, String qName, 63 Attributes attributes) throws SAXException { 64 // TODO Auto-generated method stub 65 chann = new channel(); 66 if (localName.equals("item")) { 67 for (int i = 0; i < attributes.getLength(); i++) { 68 if (attributes.getLocalName(i).equals("id")) { 69 chann.setId(attributes.getValue(i)); 70 } else if (attributes.getLocalName(i).equals("url")) { 71 chann.setUrl(attributes.getValue(i)); 72 } 73 } 74 currentState = ITEM; 75 return; 76 } 77 currentState = 0; 78 return; 79 } 80 } 1 private List<channel> getChannelList() throws ParserConfigurationException, SAXException, IOException2 {3 //實例化一個SAXParserFactory對象4 SAXParserFactory factory=SAXParserFactory.newInstance();5 SAXParser parser;6 //實例化SAXParser對象,創(chuàng)建XMLReader對象,解析器7 parser=factory.newSAXParser();8 XMLReader xmlReader=parser.getXMLReader();9 //實例化handler,事件處理器 10 SAXPraserHelper helperHandler=new SAXPraserHelper(); 11 //解析器注冊事件 12 xmlReader.setContentHandler(helperHandler); 13 //讀取文件流 14 InputStream stream=getResources().openRawResource(R.raw.channels); 15 InputSource is=new InputSource(stream); 16 //解析文件 17 xmlReader.parse(is); 18 return helperHandler.getList(); 19 }從第二部分代碼,可以看出使用SAX解析XML的步驟:
1、實例化一個工廠SAXParserFactory
2、實例化SAXPraser對象,創(chuàng)建XMLReader 解析器
3、實例化handler,處理器
4、解析器注冊一個事件
4、讀取文件流
5、解析文件
二、使用pull方式解析
基礎(chǔ)知識:
? ? ? 在android系統(tǒng)中,很多資源文件中,很多都是xml格式,在android系統(tǒng)中解析這些xml的方式,是使用pul解析器進行解析的,它和sax解析一樣(個人感覺要比sax簡單點),也是采用事件驅(qū)動進行解析的,當(dāng)pull解析器,開始解析之后,我們可以調(diào)用它的next()方法,來獲取下一個解析事件(就是開始文檔,結(jié)束文檔,開始標(biāo)簽,結(jié)束標(biāo)簽),當(dāng)處于某個元素時可以調(diào)用XmlPullParser的getAttributte()方法來獲取屬性的值,也可調(diào)用它的nextText()獲取本節(jié)點的值。
其實以上描述,就是對整個解析步驟的一個描述,看看代碼吧
1 private List<Map<String, String>> getData() {2 List<Map<String, String>> list = new ArrayList<Map<String, String>>();3 XmlResourceParser xrp = getResources().getXml(R.xml.channels);4 5 try {6 // 直到文檔的結(jié)尾處7 while (xrp.getEventType() != XmlResourceParser.END_DOCUMENT) {8 // 如果遇到了開始標(biāo)簽9 if (xrp.getEventType() == XmlResourceParser.START_TAG) { 10 String tagName = xrp.getName();// 獲取標(biāo)簽的名字 11 if (tagName.equals("item")) { 12 Map<String, String> map = new HashMap<String, String>(); 13 String id = xrp.getAttributeValue(null, "id");// 通過屬性名來獲取屬性值 14 map.put("id", id); 15 String url = xrp.getAttributeValue(1);// 通過屬性索引來獲取屬性值 16 map.put("url", url); 17 map.put("name", xrp.nextText()); 18 list.add(map); 19 } 20 } 21 xrp.next();// 獲取解析下一個事件 22 } 23 } catch (XmlPullParserException e) { 24 // TODO Auto-generated catch block 25 e.printStackTrace(); 26 } catch (IOException e) { 27 // TODO Auto-generated catch block 28 e.printStackTrace(); 29 } 30 31 return list; 32 }?
三、使用Dom方式解析
基礎(chǔ)知識:
? ? ?最后來看看Dom解析方式,這種方式解析自己之前也沒有用過(在j2ee開發(fā)中比較常見,沒有做過這方面的東西),在Dom解析的過程中,是先把dom全部文件讀入到內(nèi)存中,然后使用dom的api遍歷所有數(shù)據(jù),檢索想要的數(shù)據(jù),這種方式顯然是一種比較消耗內(nèi)存的方式,對于像手機這樣的移動設(shè)備來講,內(nèi)存是非常有限的,所以對于比較大的XML文件,不推薦使用這種方式,但是Dom也有它的優(yōu)點,它比較直觀,在一些方面比SAX方式比較簡單。在xml文檔比較小的情況下也可以考慮使用dom方式。
Dom方式解析的核心代碼如下:
1 public static List<channel> getChannelList(InputStream stream)2 {3 List<channel> list=new ArrayList<channel>();4 5 //得到 DocumentBuilderFactory 對象, 由該對象可以得到 DocumentBuilder 對象6 DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();7 8 try {9 //得到DocumentBuilder對象 10 DocumentBuilder builder=factory.newDocumentBuilder(); 11 //得到代表整個xml的Document對象 12 Document document=builder.parse(stream); 13 //得到 "根節(jié)點" 14 Element root=document.getDocumentElement(); 15 //獲取根節(jié)點的所有items的節(jié)點 16 NodeList items=root.getElementsByTagName("item"); 17 //遍歷所有節(jié)點 18 for(int i=0;i<items.getLength();i++) 19 { 20 channel chann=new channel(); 21 Element item=(Element)items.item(i); 22 chann.setId(item.getAttribute("id")); 23 chann.setUrl(item.getAttribute("url")); 24 chann.setName(item.getFirstChild().getNodeValue()); 25 list.add(chann); 26 } 27 28 } catch (ParserConfigurationException e) { 29 // TODO Auto-generated catch block 30 e.printStackTrace(); 31 } catch (SAXException e) { 32 // TODO Auto-generated catch block 33 e.printStackTrace(); 34 } catch (IOException e) { 35 // TODO Auto-generated catch block 36 e.printStackTrace(); 37 } 38 39 return list; 40 }總結(jié)一下Dom解析的步驟(和sax類似)
1、調(diào)用 DocumentBuilderFactory.newInstance() 方法得到 DOM 解析器工廠類實例。
2、調(diào)用解析器工廠實例類的?newDocumentBuilder() 方法得到 DOM 解析器對象
3、調(diào)用 DOM 解析器對象的 parse()?方法解析 XML 文檔得到代表整個文檔的 Document 對象。
四、總結(jié)
? ? ? ?除以上三種外還有很多解析xml的方法,比如DOM4J、JDOM等等。但其基本的解析方式包含兩種,一種是事件驅(qū)動的(代表SAX),另一種方式是基于文檔結(jié)構(gòu)(代表DOM)。其他的只不過語法不一樣而已。
轉(zhuǎn)載于:https://my.oschina.net/u/268088/blog/751064
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅持創(chuàng)作打卡瓜分現(xiàn)金大獎總結(jié)
以上是生活随笔為你收集整理的android xml解析的三种方式的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 财政拨款是什么意思
- 下一篇: 运满满司机如何提现(究竟是运满满还是祸满