在android開發中,經常用到去解析xml文件,常見的解析xml的方式有一下三種:SAX、Pull、Dom解析方式。
? ? ?今天解析的xml示例(channels.xml)如下:


1 <?xml version="1.0" encoding="utf-8"?> 2 <channel> 3 <item id="0" url="http://www.baidu.com">百度</item> 4 <item id="1" url="http://www.qq.com">騰訊</item> 5 <item id="2" url="http://www.sina.com.cn">新浪</item> 6 <item id="3" url="http://www.taobao.com">淘寶</item> 7 </channel>
?
一、使用sax方式解析
?基礎知識:
? ? ?這種方式解析是一種基于事件驅動的api,有兩個部分,解析器和事件處理器,解析器就是XMLReader接口,負責讀取XML文檔,和向事件處理器發送事件(也是事件源),事件處理器ContentHandler接口,負責對發送的事件響應和進行XML文檔處理。
? ? ?下面是ContentHandler接口的常用方法
? ? ?public abstract void characters (char[] ch, int start, int length)
? ? ? 這個方法來接收字符塊通知,解析器通過這個方法來報告字符數據塊,解析器為了提高解析效率把讀到的所有字符串放到一個字符數組(ch)中,作為參數傳遞給character的方法中,如果想獲取本次事件中讀取到的字符數據,需要使用start和length屬性。
? ??public abstract void startDocument () 接收文檔開始的通知
? ???public abstract void endDocument () 接收文檔結束的通知
? ??public abstract void startElement (String uri, String localName, String qName, Attributes atts) 接收文檔開始的標簽
? ??public abstract void endElement (String uri, String localName, String qName) 接收文檔結束的標簽
? ? 在一般使用中為了簡化開發,在org.xml.sax.helpers提供了一個DefaultHandler類,它實現了ContentHandler的方法,我們只想繼承DefaultHandler方法即可。
? ?另外SAX解析器提供了一個工廠類:SAXParserFactory,SAX的解析類為SAXParser 可以調用它的parser方法進行解析。


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 * 接收文檔結束通知 31 */ 32 @Override 33 public void endDocument() throws SAXException { 34 // TODO Auto-generated method stub 35 super.endDocument(); 36 } 37 38 /* 39 * 接收標簽結束通知 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 * 標簽開始通知 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, IOException 2 { 3 //實例化一個SAXParserFactory對象 4 SAXParserFactory factory=SAXParserFactory.newInstance(); 5 SAXParser parser; 6 //實例化SAXParser對象,創建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對象,創建XMLReader 解析器
3、實例化handler,處理器
4、解析器注冊一個事件
4、讀取文件流
5、解析文件
?
二、使用pull方式解析
基礎知識:
? ? ? 在android系統中,很多資源文件中,很多都是xml格式,在android系統中解析這些xml的方式,是使用pul解析器進行解析的,它和sax解析一樣(個人感覺要比sax簡單點),也是采用事件驅動進行解析的,當pull解析器,開始解析之后,我們可以調用它的next()方法,來獲取下一個解析事件(就是開始文檔,結束文檔,開始標簽,結束標簽),當處于某個元素時可以調用XmlPullParser的getAttributte()方法來獲取屬性的值,也可調用它的nextText()獲取本節點的值。


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 // 直到文檔的結尾處 7 while (xrp.getEventType() != XmlResourceParser.END_DOCUMENT) { 8 // 如果遇到了開始標簽 9 if (xrp.getEventType() == XmlResourceParser.START_TAG) { 10 String tagName = xrp.getName();// 獲取標簽的名字 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方式解析
基礎知識:
? ? ?最后來看看Dom解析方式,這種方式解析自己之前也沒有用過(在j2ee開發中比較常見,沒有做過這方面的東西),在Dom解析的過程中,是先把dom全部文件讀入到內存中,然后使用dom的api遍歷所有數據,檢索想要的數據,這種方式顯然是一種比較消耗內存的方式,對于像手機這樣的移動設備來講,內存是非常有限的,所以對于比較大的XML文件,不推薦使用這種方式,但是Dom也有它的優點,它比較直觀,在一些方面比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 //得到 "根節點" 14 Element root=document.getDocumentElement(); 15 //獲取根節點的所有items的節點 16 NodeList items=root.getElementsByTagName("item"); 17 //遍歷所有節點 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 }
總結一下Dom解析的步驟(和sax類似)
1、調用 DocumentBuilderFactory.newInstance() 方法得到 DOM 解析器工廠類實例。
2、調用解析器工廠實例類的?newDocumentBuilder() 方法得到 DOM 解析器對象
3、調用 DOM 解析器對象的 parse()?方法解析 XML 文檔得到代表整個文檔的 Document 對象。
?
原文地址:http://www.cnblogs.com/JerryWang1991/archive/2012/02/24/2365507.html
?