Android XML解析

本文介绍Android平台上的XML解析方法,包括SAX、DOM及Pull解析器的使用,并提供实例代码对比不同方法的特点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >



http://www.makaidong.com/%E5%8D%9A%E5%AE%A2%E5%9B%AD%E7%89%9B/24821.shtml


一、简述
  xml语言是跨平台开发,java对xml语言支持得比较好,android系统开发应用开发层平台是java做的,所以用xml。
xml解析比较简单。xml解析就是将获取到的数据分离出来,基本的网络数据传输,需要使用xml
比如天气预报,从网上获取的是xml文件,通过xml解析可以把天气状态读出来
例:

1 <forecast_date data="2009-07-31" />
2 <condition data="晴" />
3 <humidity data="湿度: 65%" />(xml文件不全)

可得到 2009-07-31 晴 湿度:65%

还有一作用是保存你的数据,比如做个旅游网站,你需要把全国各个省、城市名称写到xml文件进行保存,在程序中通过解析读取调用。


android 平台上可用的xml解析有三种
1、simple api for xml(sax)
2、document object model(dom)
3、android附带的pull解析器

 

二、实例
分别用三种开发方法 解析如下persons.xml文件(文件放在assert目录下)

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <persons>
 3     <person id="23">
 4         <name>liming</name>
 5         <age>30</age>
 6     </person>
 7     <person id="20">
 8         <name>dehua</name>
 9         <age>25</age>
10     </person>
11 </persons>

 

还需定义个javabean 用于存放解析出来的内容

 1 package com.example.xml;
 2 
 3 public class person {
 4     private integer id;
 5     private string name;
 6     private short age;
 7 
 8     public integer getid() {
 9         return id;
10     }
11 
12     public void setid(integer id) {
13         this.id = id;
14     }
15 
16     public string getname() {
17         return name;
18     }
19 
20     public void setname(string name) {
21         this.name = name;
22     }
23 
24     public short getage() {
25         return age;
26     }
27 
28     public void setage(short age) {
29         this.age = age;
30     }
31 
32 //    @override
33 //    public string tostring() {
34 //        return "id:" + id + ", name:" + name + ", age:" + age;
35 //    }
36 }

 

1、simple api for xml(sax)

  sax是一个解析速度快并且占用内存少的xml解析器,很适合用于android等移动开发其他 设备。
sax解析xml文件采用的是事件驱动开发 ,也就是说,它并不需要解析完整个文档,在按内容顺序解析文档的开发过程 中,
sax会判断当前读到的字符是否合法xml语法中的某部分,如果符合就会触发事件。所谓事件,其实就是一些回调(callback)开发方法
这些开发方法 (事件)定义在contenthandler接口。

  直接看代码:

 1 public class xmlcontenthandler extends defaulthandler {
 2     private list<person> persons = null;
 3     private person currentperson;
 4     private string tagname = null;// 当前解析的元素标签    
 5     private static final string tag = "xmlcontenthandler"; 
 6 
 7     public list<person> getpersons() {
 8         return persons;
 9     }
10 
11     /* 
12      * 接收文档的开始的通知。
13      */
14 
15     @override
16     public void startdocument() throws saxexception {
17         persons = new arraylist<person>();
18          log.i(tag, "startdocument");  
19     }
20     
21     /* 
22      * 结束文档的开始的通知。
23      */
24 
25     @override
26     public void enddocument() throws saxexception {
27         super.enddocument();
28          log.i(tag, "enddocument");  
29     }
30 
31     /* 
32      * 接收字符数据的通知。
33      */
34 
35     @override
36     public void characters(char[] ch, int start, int length)
37             throws saxexception {
38         if (tagname != null) {
39             string data = new string(ch, start, length);
40             if (tagname.equals("name")) {
41                 this.currentperson.setname(data);
42             } else if (tagname.equals("age")) {
43                 this.currentperson.setage(short.parseshort(data));
44             }
45         }
46         log.i(tag, "characters("+ch.tostring()+","+start+","+length+")"); 
47 
48     }
49 
50     /*
51      * 
52      * 接收元素开始的通知。
53      * 参数意义如下: 
54      * namespaceuri:元素的命名空间 
55      * localname :元素的本地名称(不带前缀) 
56      * qname :元素的限定名(带前缀)
57      * atts :元素的属性集合
58      */
59 
60     @override
61     public void startelement(string namespaceuri, string localname,
62             string qname, attributes atts) throws saxexception {
63 
64         if (localname.equals("person")) {
65             currentperson = new person();
66             currentperson.setid(integer.parseint(atts.getvalue("id")));
67         }
68 
69         this.tagname = localname;
70         log.i(tag, "startelement("+namespaceuri+","+localname+","+qname+atts+")"); 
71 
72     }
73 
74     /* 
75      * 接收文档的结尾的通知。
76      * 参数意义如下:
77      * uri :元素的命名空间
78      * localname :元素的本地名称(不带前缀)
79      * name :元素的限定名(带前缀)
80      */
81     @override
82     public void endelement(string uri, string localname, string name)
83             throws saxexception {
84 
85         if (localname.equals("person")) {
86             persons.add(currentperson);
87             currentperson = null;
88         }
89 
90         this.tagname = null;
91         log.i(tag, "endelement("+uri+","+localname+","+name+")"); 
92 
93     }
94 }

 


2、document object model(dom)
  dom解析xml文件时,会将xml文件的所有内容读取到内存中,然后允许您使用dom api遍历xml树、检索所需的数据。
使用dom操作xml的代码看起来比较直观,并且,在某些方面比基于sax的实现更加简单。但是,因为dom需要将xml文件的所有内容读取到内存中,
所以内存的消耗比较大,特别对于运行android的移

此文来自: 马开东博客 转载请注明出处 网址:http://www.makaidong.com

动设备来说,因为设备的资源比较宝贵,所以建议还是采用sax来解析xml文件,
当然,如果xml文件的内容比较小采用dom是可行的。

 

 1 public class domparsexml {
 2 
 3     public list<person> readxml(inputstream instream) {
 4 
 5         list<person> persons = new arraylist<person>();
 6 
 7         documentbuilderfactory factory = documentbuilderfactory.newinstance();// 获取实例
 8 
 9         try {
10 
11             documentbuilder builder = factory.newdocumentbuilder();
12             document dom = builder.parse(instream);
13             element root = dom.getdocumentelement();
14             nodelist items = root.getelementsbytagname("person");// 查找所有person节点
15 
16             for (int i = 0; i < items.getlength(); i++) {
17 
18                 person person = new person();
19 
20                 // 得到第一个person节点
21                 element personnode = (element) items.item(i);
22 
23                 // 获取person节点的id属性值
24                 person.setid(new integer(personnode.getattribute("id")));
25 
26                 // 获取person节点下的所有子节点(标签之间的空白节点和name/age元素)
27                 nodelist childsnodes = personnode.getchildnodes();
28 
29                 for (int j = 0; j < childsnodes.getlength(); j++) {
30 
31                     node node = (node) childsnodes.item(j); // 判断是否为元素类型
32                     if (node.getnodetype() == node.element_node) {
33                         element childnode = (element) node;
34 
35                         // 判断是否name元素
36                         if ("name".equals(childnode.getnodename())) {
37 
38                             // 获取name元素下text节点,然后从text节点获取数据
39                             person.setname(childnode.getfirstchild()
40                                     .getnodevalue());
41 
42                         } else if ("age".equals(childnode.getnodename())) {
43                             person.setage(new short(childnode.getfirstchild()
44                                     .getnodevalue()));
45 
46                         }
47                     }
48                 }
49                 persons.add(person);
50             }
51             instream.close();
52         } catch (exception e) {
53             e.printstacktrace();
54         }
55 
56         return persons;
57 
58     }
59 }

 

3、android附带的pull解析器
  pull解析和sax解析很相似,都是轻量级的解析,在android的内核中已经嵌入开发 了pull,所以我们不需要再添加第三方jar包来支持pull。
pull解析和sax解析不一样的地方有(1)pull读取xml文件后触发相应的事件调用开发方法 返回的是数字(2)pull可以在程序中控制想解析到哪里就可以停止解析。

 

 1 public class pullparsexml {
 2     
 3     public list<person> readxml(inputstream instream) throws xmlpullparserexception, ioexception{
 4 
 5         list<person> persons = null;  
 6         person person = null;  
 7         xmlpullparser parser = xml.newpullparser();  
 8         parser.setinput(instream, "utf-8");  
 9           
10         int event = parser.geteventtype();//产生第一个事件  
11         while(event!=xmlpullparser.end_document){  
12             switch(event){  
13             case xmlpullparser.start_document://判断当前事件是否是文档开始事件  
14                 persons = new arraylist<person>();//初始化persons集合  
15                 break;  
16             case xmlpullparser.start_tag://判断当前事件是否是标签元素开始事件  
17                 if("person".equals(parser.getname())){//判断开始标签元素是否是person  
18                     person = new person();  
19                     person.setid(integer.parseint(parser.getattributevalue(0)));//得到person标签的属性值,并设置person的id  
20                 }  
21                 if(person!=null){  
22                     if("name".equals(parser.getname())){//判断开始标签元素是否是name  
23                         person.setname(parser.nexttext());  
24                     }else if("age".equals(parser.getname())){//判断开始标签元素是否是price  
25                         person.setage(short.parseshort(parser.nexttext()));  
26                     }  
27                 }  
28                 break;  
29             case xmlpullparser.end_tag://判断当前事件是否是标签元素结束事件  
30                 if("person".equals(parser.getname())){//判断结束标签元素是否是person  
31                     persons.add(person);//将person添加到persons集合  
32                     person = null;  
33                 }  
34                 break;  
35             }  
36             event = parser.next();//进入下一个元素并触发相应事件  
37         }//end while  
38         return persons;  
39 
40     }
41 }

 

运行界面:

绑定按钮触发的事件代码:

 1 @override
 2     protected void oncreate(bundle savedinstancestate) {
 3         super.oncreate(savedinstancestate);
 4         setcontentview(r.layout.activity_main);
 5         textview = (textview)findviewbyid(r.id.textview);  
 6         sax_prase = (button)findviewbyid(r.id.sax_prase);  
 7         dom_parse = (button)findviewbyid(r.id.dom_parse);  
 8         pull_parse = (button)findviewbyid(r.id.pull_parse);
 9         
10         
11         try {
12             instream = getassets().open("persons.xml");
13         } catch (ioexception e) {
14             // todo auto-generated catch block
15             e.printstacktrace();
16         }
17         
18         //绑定按钮监听器  
19         sax_prase.setonclicklistener(new onclicklistener() {  
20             @override  
21             public void onclick(view v) {  
22                 persons = saxparsexml(instream); 
23                 for (person person : persons) {  
24                     log.i(tag, person.getid()+":"+person.getname()+":"+person.getage()); 
25                 } 
26             }  
27         });  
28         //绑定按钮监听器  
29         dom_parse.setonclicklistener(new onclicklistener() {  
30             @override  
31             public void onclick(view v) {  
32                 
33                 domparsexml domparsexml = new domparsexml();            
34                 persons = domparsexml.readxml(instream);
35                 for (person person : persons) {  
36                     log.i(tag, person.getid()+":"+person.getname()+":"+person.getage()); 
37                 } 
38             }  
39         });  
40         pull_parse.setonclicklistener(new onclicklistener() {  
41             @override  
42             public void onclick(view v) {  
43                 
44                 pullparsexml pullparsexml = new pullparsexml();                             
45                 try {
46                     persons = pullparsexml.readxml(instream);
47                 } catch (xmlpullparserexception e) {
48                     // todo auto-generated catch block
49                     e.printstacktrace();
50                 } catch (ioexception e) {
51                     // todo auto-generated catch block
52                     e.printstacktrace();
53                 }
54                 for (person person : persons) {  
55                     log.i(tag, person.getid()+":"+person.getname()+":"+person.getage()); 
56                 } 
57                 
58             }  
59         });
60     }
61 
62     private static list<person> saxparsexml(inputstream instream) {
63         // todo auto-generated method stub
64         try {
65             saxparserfactory spf = saxparserfactory.newinstance();
66             saxparser saxparser = spf.newsaxparser(); // 创建解析器
67 
68             // 设置解析器的相关特性,http://xml.org/sax/features/namespaces = true
69             // 表示开启命名空间特性,缺省情况设为true,设置使代码更具可读性,但我加进去报错,索性注释掉
70             //saxparser.setproperty("http://xml.org/sax/features/namespaces",true);
71             xmlcontenthandler handler = new xmlcontenthandler();
72                         
73             saxparser.parse(instream, handler);
74             instream.close();
75 
76             return handler.getpersons();
77 
78         } catch (exception e) {
79 
80             e.printstacktrace();
81 
82         }
83 
84         return null;
85     }

分别点击三个按钮用不同开发方法 解析出来的结果:


三、总结
  对于三种解析xml开发方法 ,各有千秋,倾向于pull解析器,因为sax解析器操作起来太笨重,dom不适合文档较大,内存较小的场景,
唯有pull轻巧灵活,速度快,占用内存小,使用非常顺手,pull解析可以用于很多场合,例如接受google天气,rss新闻等。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值