Android解析XML——SAX、PULL、DOM

转载 2013年12月01日 22:16:07

今天和一个做培训的老师聊到了android解析xml的问题,在我的工作经历中我还没有做过解析XML的任务,有过类似的任务,但是我不会解析XML文件,于是我自己定义了一套文件格式,然后用IO流来处理,我发现那样好麻烦,于是回来学习XML解析。收录一篇文章http://www.cnblogs.com/JerryWang1991/archive/2012/02/24/2365507.html

在android开发中,经常用到去解析xml文件,常见的解析xml的方式有一下三种:SAX、Pull、Dom解析方式。最近做了一个android版的CSDN阅读器,用到了其中的两种(sax,pull),今天对android解析xml的这三种方式进行一次总结。

     今天解析的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方式解析

 基础知识:

     这种方式解析是一种基于事件驱动的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 对象。

四、总结

       除以上三种外还有很多解析xml的方法,比如DOM4J、JDOM等等。但其基本的解析方式包含两种,一种是事件驱动的(代表SAX),另一种方式是基于文档结构(代表DOM)。其他的只不过语法不一样而已。

示例程序下载地址

Android中三种常用解析XML的方式(DOM、SAX、PULL)简介及区别

XML在各种开发中都广泛应用,Android也不例外。作为承载数据的一个重要角色,如何读写XML成为Android开发中一项重要的技能。今天就由我向大家介绍一下在Android平台下几种常见的XML解...
  • cangchen
  • cangchen
  • 2015年03月03日 10:17
  • 3710

利用Dom,Sax,Pull三种方式解析xml文件

最近找工作,看到许多公司的要求里都写了要会xml解析,所以就把之前的xml解析知识又重新回顾了一下,写个小例子. 解析xml文件常用的几种方式也就dom,sax,pull了,并且面试官经常问到的也是这...
  • qiang_xi
  • qiang_xi
  • 2015年11月29日 20:15
  • 1213

XML使用SAX解析与PULL解析的区别

XML使用SAX解析与PULL解析的区别在最近的应用中,经常会用到对XML的解析,但是一直有一个疑问就是SAX解析与PULL解析的区别到底是什么。搜索了相关的问题,整理如下,以便大家查询。我们知道,S...
  • zhliro
  • zhliro
  • 2015年07月10日 15:18
  • 1985

DOM SAX和PULL解析

DOM SAX pull
  • qq_33344834
  • qq_33344834
  • 2016年07月09日 11:11
  • 293

dom、sax、pull解析的优缺点

一、dom解析: 将整个xml文件装载到内存中,如果内存不足就挂掉,小文件dom比较占优势。 使用场合:一旦解析了文档还需多次访问这些数据;硬件资源充足(内存、CPU)。  二、sax解析:...
  • u013470176
  • u013470176
  • 2015年12月15日 10:23
  • 1419

sax和dom在解析xml文档时有什么区别

当你需要处理XML文档时,你的首要选择是使用DOM(文档对象模型)还是使用SAX(用于XML的简单API),即当前使用的两个主要的XML API。你可以使用任何一种(或者在同一时间使用两种)来处理XM...
  • zhupengqq
  • zhupengqq
  • 2016年04月18日 18:31
  • 1290

xml文件的解析解析方式及Dom解析与Sax解析的区别

一、简单概述你常见的xml解析方式 ①DOM
  • Crazy9599
  • Crazy9599
  • 2014年06月03日 19:20
  • 1147

XML之四种解析dom,sax,jdom,dom4j原理及性能比较

XML:四种解析器(dom,sax,jdom,dom4j)原理及性能比较   dom是解析xml的底层接口之一(另一种是sax).而jdom和dom4j则是基于底层api的更高级封装。dom是通...
  • qq_35370485
  • qq_35370485
  • 2017年05月24日 08:56
  • 874

XML两种解析思想:DOM和SAX

一、什么是XML英文全称为Extensible Markup Language,翻译过来为可扩展标记语言。现实生活中存在着大量的数据,在这些数据之间往往存在一定的关系,我们希望能在计算机中保存和处理这...
  • wujingjing_crystal
  • wujingjing_crystal
  • 2016年09月27日 18:31
  • 793

Java之DOM,SAX,JDOM,DOM4J,四种解析xml方法比较

4种解析方式的比较 1.DOM解析    优点:a.形成了树结构,直观好理解,代码更易编写          b.解析过程中树结构保留在内存中,方便修改 缺点:         a.当xml...
  • qq_31028891
  • qq_31028891
  • 2016年08月13日 21:29
  • 1579
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Android解析XML——SAX、PULL、DOM
举报原因:
原因补充:

(最多只允许输入30个字)