你的分享就是我们的动力 ---﹥

Android中XML文件的三种解析方式

时间:2011-09-24 11:44来源:www.chengxuyuans.com 点击:

今天学习了xml文件的三种解析方式,其中包括在学习java时学习的SAX和DOM这两种解析方法。在Android中有一种开源的PULL解析方法,今天我将他们的具体用法和大家分享下。

业务需求:

  给定一个xml文件,要求分别用SAX,DOM,PULL三种方法对xml文件进行解析。

运行效果图如下:

下面是具体实现步骤:

首先我们需要一个xml文件,下面是我xml文件的存放位置。

该xml文件中的内容我写的比较简单。仅供实现这个功能。下面是我的xml文件的内容。

persons.xml:

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <persons>
 3     <person id="1">
 4         <name>刘备</name>
 5         <age>12</age>    
 6     </person>
 7     <person id="2">
 8         <name>刘欢</name>
 9         <age>14</age>    
10     </person>
11     <person id="3">
12         <name>李明</name>
13         <age>15</age>    
14     </person>
15 </persons>

我们可以看到xml文件中只有一个person对象,所以我们必须定义一个person类。

在Android中为了体现封装性,我们需要将不同功能的代码放在不同的包里。下面是我在实现这个功能时,各个代码存放的位置。

Person.java

 1 package cn.yj3g.entity;
 2 public class Person {
 3 
 4     private int id;
 5     private String name;
 6     private int age;
 7     public Person(int id, String name, int age) {
 8         super();
 9         this.id = id;
10         this.name = name;
11         this.age = age;
12     }
13     public Person() {
14         super();
15     }
16     public int getId() {
17         return id;
18     }
19 
20     public void setId(int id) {
21         this.id = id;
22     }
23     public String getName() {
24         return name;
25     }
26     public void setName(String name) {
27         this.name = name;
28     }
29     public int getAge() {
30         return age;
31     }
32     public void setAge(int age) {
33         this.age = age;
34     }
35     @Override
36     public String toString() {
37         return "Person [id=" + id + ", name=" + name + ", age=" + age + "]";
38     }
39 }

由于三种解析方法都实现了一个功能,就是对xml文件进行解析,所以在这里我们可以将解析方法定义为一个接口,三种解析方法都实现这个接口。下面是我定义的一个接口

IXmlParseService:

 1 package cn.yj3g.service;
 2 
 3 import java.io.InputStream;
 4 import java.util.List;
 5 import cn.yj3g.entity.Person;
 6 //定义一个接口
 7 public interface IXmlParseService {
 8     //接口中的一个解析方法。如果引用这个接口,就要实现这个方法,这样做更简便,封装性更好。
 9     public List<Person> getPersonsByParseXml(InputStream is) throws Exception;
10 }

下来就是具体用三种方式对xml实现解析。下面是三种解析方式的具体代码:

<1>DOM解析    DomParseService:

 1 package cn.yj3g.service;
 2 
 3 import java.io.InputStream;
 4 import java.util.ArrayList;
 5 import java.util.List;
 6 import javax.xml.parsers.DocumentBuilder;
 7 import javax.xml.parsers.DocumentBuilderFactory;
 8 import org.w3c.dom.Document;
 9 import org.w3c.dom.Element;
10 import org.w3c.dom.Node;
11 import org.w3c.dom.NodeList;
12 import cn.yj3g.entity.Person;
13 /**
14  * DOM解析器在解析XML文档时,会把文档中的所有元素,按照其出现的层次关系,解析成一个个Node对象(节点)。Node对象提供了一系列常量来代表结点的类型
15  * ,当开发人员获得某个Node类型后,就可以把Node节点转换成相应节点对象(Node的子类对象),以便于调用其特有的方法。
16  * Node对象提供了相应的方法去获得它的父结点或子结点。编程人员通过这些方法就可以读取整个XML文档的内容、或添加、修改、删除XML文档的内容.
17  * 
18  * 缺点:
19  * 一次性的完全加载整个xml文件,需要消耗大量的内存。
20  */
21 public class DomParseService implements IXmlParseService {
22 
23     @Override
24     public List<Person> getPersonsByParseXml(InputStream is) throws Exception {
25         List<Person> list = null;
26         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
27         DocumentBuilder builder = factory.newDocumentBuilder();
28         Document document = builder.parse(is);
29         // 得到根元素,这里是persons
30         Element root = document.getDocumentElement();
31         // 得到一个集合,里面存放在xml文件中所有的person
32         NodeList nodeList = root.getElementsByTagName("person");
33         //
34         if (nodeList == null || nodeList.getLength() == 0) {
35             return null;
36         }
37         // 初始化
38         list = new ArrayList<Person>();
39 
40         for (int i = 0; i < nodeList.getLength(); i++) {
41             // xml中的person标签
42             Element element = (Element) nodeList.item(i);
43             Person p = new Person();
44             // 得到person的id属性
45             int id = Integer.parseInt(element.getAttribute("id"));
46             p.setId(id);
47             // 得到name
48             String name = getAttrText(element, "name");
49             p.setName(name);
50             // 得到age
51             String age = getAttrText(element, "age");
52             p.setAge(new Integer(age));
53 
54             list.add(p);
55         }
56         return list;
57     }
58 
59     /**
60      * 获得指定元素的子元素中的文本内容
61      */
62     public String getAttrText(Element element, String name) {
63         NodeList nodeList2 = element.getChildNodes();
64         Node node = null;
65         for (int i = 0; i < nodeList2.getLength(); i++) {
66             node = nodeList2.item(i);
67             if (node.getNodeName().equals(name)) {
68                 return node.getTextContent();
69             }
70         }
71         return null;
72     }
73 }

<2>SAX解析  SAXParseService:

package cn.yj3g.service;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import cn.yj3g.entity.Person;
/**
 * 优点:SAX解析允许在读取文档的时候,即对文档进行处理,而不必等到整个文档装载完才会文档进行操作。
 * 
 */
public class SAXParseService implements IXmlParseService {
    public List<Person> getPersonsByParseXml(InputStream is) throws Exception {

        SAXParserFactory factory = SAXParserFactory.newInstance();
        SAXParser parser = factory.newSAXParser();
        saxHandler handler = new saxHandler();
        //
        parser.parse(is, handler);
        return handler.getList();
    }
    // 自定义一个handler实现DefaultHandler并 重写它的相关方法
    private class saxHandler extends DefaultHandler {
        String currunt = null;
        List<Person> list = null;
        Person p = null;

        @Override
        public void startDocument() throws SAXException {
            list = new ArrayList<Person>();
        }

        @Override
        public void endDocument() throws SAXException {
        }

        // 开始解析元素
        @Override
        public void startElement(String uri, String localName, String qName,
                Attributes attributes) throws SAXException {
            if ("person".equals(localName)) {
                p = new Person();
                p.setId(Integer.parseInt(attributes.getValue("id")));
            } else if ("name".equals(localName) || "age".equals(localName)) {
                currunt = localName;
            }
        }

        // 元素解析结束
        @Override
        public void endElement(String uri, String localName, String qName)
                throws SAXException {
            if ("person".equals(localName)) {
                list.add(p);
            } else if ("name".equals(localName) || "age".equals(localName)) {
                currunt = null;
            }
        }

        // 解析文本
        @Override
        public void characters(char[] ch, int start, int length)
                throws SAXException {
            String s = new String(ch, start, length);
            if ("name".equals(currunt)) {
                p.setName(s);
            } else if ("age".equals(currunt)) {
                p.setAge(Integer.parseInt(s));
            }
        }

        // 返回list
        public List<Person> getList() {
            return list;
        }
    }
}

<3>PULL解析  PullParseService:

package cn.yj3g.service;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserFactory;
import cn.yj3g.entity.Person;
/**
 * 优点:不是一次加载,中途可以停止。
 *
 */
public class PullParseService implements IXmlParseService {
    public List<Person> getPersonsByParseXml(InputStream is) throws Exception {

        List<Person> list = null;
        Person p = null;
        XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
        XmlPullParser parser = factory.newPullParser();
        //设置输入流
        parser.setInput(is, "utf-8");
        //parser的几种事件类型
        int type = parser.getEventType();
        while (type != XmlPullParser.END_DOCUMENT) {
            //
            String typename = parser.getName();
            switch (type) {
            //文档开始 -->xml中的persons
            case XmlPullParser.START_DOCUMENT:
                list = new ArrayList<Person>();
                break;
            //元素开始
            case XmlPullParser.START_TAG:
                if ("person".equals(typename)) {
                    p = new Person();
                    p.setId(Integer.parseInt(parser.getAttributeValue(0)));
                    //
                } else if ("name".equals(typename)) {
                    p.setName(parser.nextText());
                    //
                } else if ("age".equals(typename)) {
                    p.setAge(Integer.parseInt(parser.nextText()));
                }
                break;
            //元素结束    
            case XmlPullParser.END_TAG:
                if ("person".equals(typename)) {
                    list.add(p);
                    p=null;
                    break;
                }
            }
            //最最重要的一步,pull解析中的特有的方法,解析下一个标签
            type = parser.next();
        }
        return list;
    }
}

下来就是在主界面上通过Button设置监听来调用三种解析方法对xml文件进行解析,并将解析出来的数据放在一个ListView中。

主界面: XMLParseActivity:

 1 package cn.yj3g.XMLParseActivity;
 2 
 3 import java.io.InputStream;
 4 import java.util.ArrayList;
 5 import java.util.HashMap;
 6 import java.util.List;
 7 import java.util.Map;
 8 import android.app.ListActivity;
 9 import android.content.res.AssetManager;
10 import android.os.Bundle;
11 import android.view.View;
12 import android.view.View.OnClickListener;
13 import android.widget.SimpleAdapter;
14 import cn.yj3g.TL23_xml_test.R;
15 import cn.yj3g.entity.Person;
16 import cn.yj3g.service.DomParseService;
17 import cn.yj3g.service.PullParseService;
18 import cn.yj3g.service.SAXParseService;
19 
20 public class XMLParseActivity extends ListActivity implements
21         OnClickListener {
22     @Override
23     public void onCreate(Bundle savedInstanceState) {
24         super.onCreate(savedInstanceState);
25         setContentView(R.layout.main);
26 
27         // 找到Button按钮并添加监听
28         findViewById(R.id.btn_dom).setOnClickListener(this);
29         findViewById(R.id.btn_sax).setOnClickListener(this);
30         findViewById(R.id.btn_pull).setOnClickListener(this);
31     }
32 
33     public void onClick(View v) {
34         int id = v.getId();
35         //定义一个List容器来存放Person对象
36         List<Person> list = null;
37         //
38         InputStream is = null;
39         AssetManager manager = getAssets();
40         try {
41             //找到解析的文件
42             is = manager.open("persons.xml");
43             switch (id) {
44             case R.id.btn_dom:
45                 //调用DOM解析方法对文件进行解析
46                 list = new DomParseService().getPersonsByParseXml(is);
47                 break;
48             case R.id.btn_sax:
49                 //调用SAX解析方法对文件进行解析
50                 list = new SAXParseService().getPersonsByParseXml(is);
51                 break;
52             case R.id.btn_pull:
53                 //调用PULL解析方法对文件进行解析
54                 list = new PullParseService().getPersonsByParseXml(is);
55                 break;
56             default:
57                 break;
58             }
59         } catch (Exception e) {
60             e.printStackTrace();
61         }
62         showUI(list);
63     }
64     
65     //运用Adapter方法将所得到的List<Person>显示在ListView中
66     public void showUI(List<Person> list) {
67         List<Map<String, Object>> data = new ArrayList<Map<String, Object>>();
68         for (Person p : list) {
69             Map<String, Object> map = new HashMap<String, Object>();
70             map.put("id", p.getId());
71             map.put("name", p.getName());
72             map.put("age", p.getAge());
73             data.add(map);
74         }
75         String[] from = { "id", "name", "age" };
76         int[] to = { R.id.tv_id, R.id.tv_name, R.id.tv_age };
77         SimpleAdapter adapter = new SimpleAdapter(this, data,
78                 R.layout.person_list_item, from, to);
79         setListAdapter(adapter);
80     }
81 }

我将布局文件也附在下面供大家参考吧。

main.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <LinearLayout 
        android:orientation="horizontal"
        android:layout_width="fill_parent"
        android:layout_height="50dip"
        android:background="#222222">
        <Button  android:id="@+id/btn_dom"
            android:layout_width="fill_parent" 
            android:layout_height="wrap_content" 
            android:text="DOM显示"
            android:layout_weight="1.0"
            android:layout_gravity="center"/>
        <Button  android:id="@+id/btn_sax"
            android:layout_width="fill_parent" 
            android:layout_height="wrap_content" 
            android:text="SAX显示"
            android:layout_weight="1.0"
            android:layout_gravity="center"/>
        <Button  android:id="@+id/btn_pull"
            android:layout_width="fill_parent" 
            android:layout_height="wrap_content" 
            android:text="PULL显示"
            android:layout_weight="1.0"
            android:layout_gravity="center"/>
    </LinearLayout>
    <LinearLayout   
    android:orientation="horizontal"
      android:layout_height="wrap_content" 
       android:layout_width="fill_parent">
        <TextView  
            android:layout_width="fill_parent" 
            android:layout_height="wrap_content" 
            android:text="ID"
            android:layout_weight="1.0"
            android:layout_gravity="center"/>
         <TextView  
            android:layout_width="fill_parent" 
            android:layout_height="wrap_content" 
            android:text="姓名"
            android:layout_weight="1.0"
            android:layout_gravity="center"/>
        <TextView  
            android:layout_width="fill_parent" 
            android:layout_height="wrap_content" 
            android:text="年龄"
            android:layout_weight="1.0"
            android:layout_gravity="center"/>
       </LinearLayout>
    <ListView android:id="@android:id/list"  
        android:layout_width="fill_parent" 
        android:layout_height="fill_parent" 
        android:layout_weight="1"/>
</LinearLayout>

person_list_item.xml:

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <LinearLayout
 3   xmlns:android="http://schemas.android.com/apk/res/android"
 4   android:orientation="horizontal"
 5   android:layout_width="match_parent"
 6   android:layout_height="match_parent">
 7     <TextView android:id="@+id/tv_id"
 8         android:layout_width="match_parent"
 9           android:layout_height="wrap_content"
10           android:layout_weight="1"/>
11     <TextView android:id="@+id/tv_name"
12         android:layout_width="match_parent"
13           android:layout_height="wrap_content"
14           android:layout_weight="1"/>
15     <TextView android:id="@+id/tv_age"
16         android:layout_width="match_parent"
17           android:layout_height="wrap_content"
18           android:layout_weight="1"/>
19 </LinearLayout>

这样我们这个项目就做好了,就可以实现解析xml的功能了。运行效果如最前面的效果图。

以上就是三种方式实现对XML文件的解析。希望大家不吝指教。

本文地址http://www.chengxuyuans.com/Android/Android_xml.html