android xml解析的三種方式

在android開發中,常常用到去解析xml文件,常見的解析xml的方式有一下三種:SAX、Pull、Dom解析方式。最近作了一個android版的CSDN閱讀器,用到了其中的兩種(sax,pull),今天對android解析xml的這三種方式進行一次總結。android

     今天解析的xml示例(channels.xml)以下:api

複製代碼

<?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>

複製代碼

 

 1、使用sax方式解析數組

 基礎知識:dom

     這種方式解析是一種基於事件驅動的api,有兩個部分,解析器和事件處理器,解析器就是XMLReader接口,負責讀取XML文檔,和向事件處理器發送事件(也是事件源),事件處理器ContentHandler接口,負責對發送的事件響應和進行XML文檔處理。ide

     下面是ContentHandler接口的經常使用方法ui

     public abstract void characters (char[] ch, int start, int length)url

      這個方法來接收字符塊通知,解析器經過這個方法來報告字符數據塊,解析器爲了提升解析效率把讀到的全部字符串放到一個字符數組(ch)中,做爲參數傳遞給character的方法中,若是想獲取本次事件中讀取到的字符數據,須要使用start和length屬性。.net

    public abstract void startDocument () 接收文檔開始的通知xml

     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的步驟:

一、實例化一個工廠SAXParserFactory

二、實例化SAXPraser對象,建立XMLReader 解析器

三、實例化handler,處理器

四、解析器註冊一個事件

四、讀取文件流

五、解析文件

2、使用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     }

複製代碼

 

3、使用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相似)

一、調用 DocumentBuilderFactory.newInstance() 方法獲得 DOM 解析器工廠類實例。

二、調用解析器工廠實例類的 newDocumentBuilder() 方法獲得 DOM 解析器對象

三、調用 DOM 解析器對象的 parse() 方法解析 XML 文檔獲得表明整個文檔的 Document 對象。

4、總結

       除以上三種外還有不少解析xml的方法,好比DOM4J、JDOM等等。但其基本的解析方式包含兩種,一種是事件驅動的(表明SAX),另外一種方式是基於文檔結構(表明DOM)。其餘的只不過語法不同而已。

相關文章
相關標籤/搜索