Android XML解析

解析XML有三种方式:Dom、SAX、Pull

其中pull解析器运行方式与SAX类似。

我们首先认识pull解析器:http://developer.android.com/intl/zh-cn/reference/org/xmlpull/v1/XmlPullParser.html

Th following event types are seen by next()

START_TAG
An XML start tag was read.
TEXT
Text content was read; the text content can be retrieved using the getText() method. (when in validating mode next() will not report ignorable whitespace, use nextToken() instead)
END_TAG
An end tag was read
END_DOCUMENT
No more events are available

1.解析
获取解析器: Xml.newPullParser()
设置输入流: parser.setInput(InputStream, String)
获取当前事件类型: parser.getEventType(), 
获取下一个事件类型: parser.next()
获取标签名: parser.getName()
获取属性值: parser.getAttributeValue(int)、getAttributeValue(null,"id")
获取下一个文本: parser.nextText()
2.生成
获取解析器:
设置输出流:
开始文档:
结束文档:
开启标签:
结束标签:
设置属性:
设置文本:

下面我们用一个实例来看看:

在src下面新建presons.xml

 1 <?xml version='1.0' encoding='UTF-8' standalone='yes' ?>
 2 <persons>
 3     <person id="1">
 4         <name>范冰冰</name>
 5         <age>31</age>
 6     </person>
 7     <person id="2">
 8         <name>林志玲</name>
 9         <age>38</age>
10     </person>
11     <person id="3">
12         <name>杨幂</name>
13         <age>26</age>
14     </person>
15 </persons>
View Code

然后在包中创建Person.java、PersonService.java、PersonTest.java

 1 public class PersonService {
 2     
 3     public List<Person> loadPersons(InputStream in) throws Exception {
 4         XmlPullParser parser = Xml.newPullParser();        // 获取解析器
 5         parser.setInput(in, "UTF-8");                    // 设置输入流, 指定码表
 6             
 7         ArrayList<Person> persons = new ArrayList<Person>();
 8         Person p = null;
 9         
10         // 最初type赋值为第一个事件, 只要不是文档结束就循环, 每次循环后解析下一个事件
11         for (int type = parser.getEventType(); type != XmlPullParser.END_DOCUMENT; type = parser.next()) {
12             if (type == XmlPullParser.START_TAG) {                // 如果遇到了标签开始事件
13                 if (parser.getName().equals("person")) {        // 如果标签名为"person"
14                     p = new Person();                            // 创建对象
15                     String id = parser.getAttributeValue(0);    // 获取第一个属性的属性值
16                     p.setId(Integer.parseInt(id));                // 转为int, 设置id
17                     persons.add(p);                                // 装入集合
18                 } else if (parser.getName().equals("name")) {    // 如果标签名为"name"
19                     String name = parser.nextText();            // 获取下一个文本
20                     p.setName(name);                            // 设置name
21                 } else if (parser.getName().equals("age")) {    // 如果标签名为"age"
22                     String age = parser.nextText();                // 获取下一个文本
23                     p.setAge(Integer.parseInt(age));            // 设置age
24                 }
25             } 
26         }
27         
28         return persons;
29     }
30 
31     public void savePersons(List<Person> persons, OutputStream out) throws IOException {
32         XmlSerializer serializer = Xml.newSerializer();        // 获取序列化工具
33         serializer.setOutput(out, "UTF-8");                    // 设置输出流, 指定码表
34         
35         serializer.startDocument("UTF-8", true);    // 开始文档
36         serializer.startTag(null, "persons");        // 开始标签
37         
38         for (Person p : persons) {
39             serializer.startTag(null, "person");
40             serializer.attribute(null, "id", p.getId().toString());        // 设置属性
41             
42             serializer.startTag(null, "name");
43             serializer.text(p.getName());            // 设置文本
44             serializer.endTag(null, "name");
45             
46             serializer.startTag(null, "age");
47             serializer.text(p.getAge().toString());
48             serializer.endTag(null, "age");
49             
50             serializer.endTag(null, "person");
51         }
52         
53         serializer.endTag(null, "persons");            // 结束标签
54         serializer.endDocument();                    // 结束文档
55     }
56 
57 }
View Code
 1 public class PersonTest extends AndroidTestCase {
 2 
 3     public void testLoad() throws Exception {
 4         PersonService service = new PersonService();
 5         InputStream in = PersonTest.class.getClassLoader().getResourceAsStream("persons.xml");
 6         List<Person> persons = service.loadPersons(in);
 7         for (Person p : persons) 
 8             System.out.println(p);
 9         
10         Person p = new Person(4, "张红", 18);
11         persons.add(p);
12         service.savePersons(persons, new FileOutputStream("/mnt/sdcard/persons.xml"));
13     }
14     
15 }
View Code
 1 public class Person {
 2     private Integer id;
 3     private String name;
 4     private Integer age;
 5 
 6     public Person() {
 7         super();
 8     }
 9 
10     public Person(Integer id, String name, Integer age) {
11         super();
12         this.id = id;
13         this.name = name;
14         this.age = age;
15     }
16 
17     public Integer getId() {
18         return id;
19     }
20 
21     public void setId(Integer id) {
22         this.id = id;
23     }
24 
25     public String getName() {
26         return name;
27     }
28 
29     public void setName(String name) {
30         this.name = name;
31     }
32 
33     public Integer getAge() {
34         return age;
35     }
36 
37     public void setAge(Integer age) {
38         this.age = age;
39     }
40 
41     @Override
42     public String toString() {
43         return "Person [id=" + id + ", name=" + name + ", age=" + age + "]";
44     }
45 
46 }
View Code

然后运行程序,可在日志中看到解析的数据。

(最好添加一个日志信息的过滤器,专门查看System.out输出的信息)

以上部分只讲解了PULL解析,下面我们用这三种解析方式解析同一个XML文件(在代码中注释讲解)。

需要我们解析的XML内容如下:

<?xml version='1.0' encoding='UTF-8' standalone='yes' ?>
<persons>
    <person id="1">
        <name>saber</name>
        <age>20</age>
    </person>
    <person id="2">
        <name>Archer</name>
        <age>21</age>
    </person>
    <person id="3">
        <name>Lancer</name>
        <age>26</age>
    </person>
</persons>

其存放在名为“assets”的文件夹下,取名为“test”。

整个程序代码文件如下:

接下来,实现一个实体类,该类的属性应与XML文件对应,名为“Person.java”,其实现如下:

package com.topcsa.entity;

public class Person {
    private Integer id;
    private String name;
    private Integer age;

    public Person() {
        super();
    }

    public Person(Integer id, String name, Integer age) {
        super();
        this.id = id;
        this.name = name;
        this.age = age;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person [id=" + id + ", name=" + name + ", age=" + age + "]";
    }

}

名为“XmlUtils.java”的文件实现如下:

package com.topcsa.utils;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

import com.topcsa.entity.Person;

import android.content.Context;
import android.util.Xml;

public class XmlUtils {

    public List<Person> XmlPullParse(Context con) {
        InputStream inputStream = null;
        ArrayList<Person> persons = new ArrayList<Person>();
        Person p = null;
        XmlPullParser parser = Xml.newPullParser(); // 获取解析器
        // 得到文件流,并设置编码方式
        try {
            inputStream = con.getResources().getAssets().open("test.xml");
            parser.setInput(inputStream, "UTF-8"); // 设置输入流, 指定码表
            // 最初type赋值为第一个事件, 只要不是文档结束就循环, 每次循环后解析下一个事件
            for (int type = parser.getEventType(); type != XmlPullParser.END_DOCUMENT; type = parser
                    .next()) {
                if (type == XmlPullParser.START_TAG) { // 如果遇到了标签开始事件
                    if (parser.getName().equals("person")) { // 如果标签名为"person"
                        p = new Person(); // 创建对象
                        String id = parser.getAttributeValue(0); // 获取第一个属性的属性值
                        p.setId(Integer.parseInt(id)); // 转为int, 设置id
                        persons.add(p); // 装入集合
                    } else if (parser.getName().equals("name")) { // 如果标签名为"name"
                        String name = parser.nextText(); // 获取下一个文本
                        p.setName(name); // 设置name
                    } else if (parser.getName().equals("age")) { // 如果标签名为"age"
                        String age = parser.nextText(); // 获取下一个文本
                        p.setAge(Integer.parseInt(age)); // 设置age
                    }
                    
                }
            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (XmlPullParserException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return persons;

    }

    public List<Person> XmlSaxParse(Context con) {

        List<Person> persons = null;
        // 建立Sax解析工厂
        SAXParserFactory factory = SAXParserFactory.newInstance();
        try {
            // 取得SaxParser对象
            SAXParser parser = factory.newSAXParser();
            // 获取事件源
            XMLReader xmlReader = parser.getXMLReader();
            // 设置sax解析器
            PersonSaxHandler handler = new PersonSaxHandler();
            xmlReader.setContentHandler(handler);
            // 解析xml文档
            xmlReader.parse(new InputSource(con.getAssets().open("test.xml")));
            persons = handler.getPersons();
        } catch (ParserConfigurationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (SAXException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return persons;

    }

    public List<Person> XmlDomParse(Context con) {
        List<Person> persons = new ArrayList<Person>();
        DocumentBuilderFactory factory = null;
        DocumentBuilder builder = null;
        Document document = null;
        InputStream inputStream = null;
        // 建立DocumentBuilderFactory对象,用于取得DocumentBuilder
        factory = DocumentBuilderFactory.newInstance();
        try {
            // 找到XML文档
            inputStream = con.getResources().getAssets().open("test.xml");
            // 通过DocumentBuilderFactory取得DocumentBuilder
            builder = factory.newDocumentBuilder();
            // 读取指定路径的XML文件
            document = builder.parse(inputStream);
            // 找到根Element
            Element root = document.getDocumentElement();
            NodeList nodes = root.getElementsByTagName("person");
            // 遍历所有根节点下的子节点,persons下的所有person
            Person person = null;
            for (int i = 0; i < nodes.getLength(); i++) {
                person = new Person();
                // 获取person元素节点
                Element personElement = (Element) (nodes.item(i));
                // 获取person中id属性值
                person.setId(Integer.parseInt(personElement.getAttribute("id")));
                // 获取person下name标签
                Element personName = (Element) personElement
                        .getElementsByTagName("name").item(0);
                person.setName(personName.getFirstChild().getNodeValue());
                // 获取person下age标签
                Element personAge = (Element) personElement
                        .getElementsByTagName("age").item(0);
                person.setAge(Integer.parseInt(personAge.getFirstChild()
                        .getNodeValue()));
                persons.add(person);
            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (ParserConfigurationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (SAXException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return persons;

    }
    
    //Sax解析方式需要的类
    class PersonSaxHandler extends DefaultHandler {

        private List<Person> list = null;
        private String elementName = null;
        private Person person = null;

        @Override
        public void startDocument() throws SAXException {// 文档开始,实例化集合
            // TODO Auto-generated method stub
            this.list = new ArrayList<Person>();
        }

        // 元素开始
        @Override
        public void startElement(String uri, String localName, String qName,
                Attributes attributes) throws SAXException {
            localName = localName.toLowerCase().trim();
            // 如果读取的是person标签开始,则实例化Person
            if (localName.equals("person")) {
                this.person = new Person();
                // 导航到person开始节点后
                this.person.setId(Integer.parseInt(attributes.getValue("id")));
            }
            // 保存元素名称
            this.elementName = localName;
        }

        @Override
        public void characters(char[] ch, int start, int length)// 获取元素类容
                throws SAXException {
            if (this.elementName != null) {// 表示有元素
                String data = new String(ch, start, length);// 取得文字信息
                if (this.elementName.equals("name")) {
                    this.person.setName(data);
                } else if (this.elementName.equals("age")) {
                    this.person.setAge(Integer.parseInt(data));
                }
            }
        }

        // 元素结尾
        @Override
        public void endElement(String uri, String localName, String qName)
                throws SAXException {
            if (localName.equals("person")) {// 判断元素标记是"person"
                this.list.add(this.person);// 向集合中保存数据
                this.person = null;// 清空对象
            }
            this.elementName = null;// 青空元素标记
        }

        public List<Person> getPersons() {// 取得全部集合
            return this.list;

        }
    }

}

MainActivity的布局文件activity_main.xml实现如下:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <Button
        android:id="@+id/btn_dom"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Dom解析" />

    <Button
        android:id="@+id/btn_sax"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Sax解析" />

    <Button
        android:id="@+id/btn_pull"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Pull解析" />

    <TextView
        android:id="@+id/tv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</LinearLayout>
View Code

MainActivity的实现如下:

package com.topcsa.zhj_test;

import java.util.ArrayList;
import java.util.List;

import android.app.Activity;
import android.os.Bundle;
import android.support.v4.widget.DrawerLayout;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

import com.topcsa.entity.Person;
import com.topcsa.utils.XmlUtils;

public class MainActivity extends Activity {
    private XmlUtils xmlutils;
    private List<Person> persons;
    private StringBuffer sb;
    private TextView tv;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button btnDom = (Button) findViewById(R.id.btn_dom);
        Button btnSax = (Button) findViewById(R.id.btn_sax);
        Button btnPull = (Button) findViewById(R.id.btn_pull);
        xmlutils = new XmlUtils();
        persons = new ArrayList<Person>();
        sb = new StringBuffer();

        btnDom.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View arg0) {
                sb.append("Dom解析:");
                persons = xmlutils.XmlDomParse(MainActivity.this);
                for (int i = 0; i < persons.size(); i++) {
                    Person person = persons.get(i);
                    sb.append("姓名:" + person.getName() + ",id:"
                            + person.getId() + ",年龄:" + person.getAge() + ";    ");

                }
                tv.setText(sb.toString());
            }
        });
        btnSax.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View arg0) {
                sb.append("Sax解析:");
                persons = xmlutils.XmlSaxParse(MainActivity.this);
                for (int i = 0; i < persons.size(); i++) {
                    Person person = persons.get(i);
                    sb.append("姓名:" + person.getName() + ",id:"
                            + person.getId() + ",年龄:" + person.getAge() + ";    ");

                }
                tv.setText(sb.toString());

            }
        });
        btnPull.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View arg0) {
                sb.append("Pull解析:");
                persons = xmlutils.XmlPullParse(MainActivity.this);
                if (persons != null) {
                    System.out.println("不为空"+persons.size());
                } else {
                    System.out.println("为空");
                }
                for (int i = 0; i < persons.size(); i++) {
                    Person person = persons.get(i);
                    sb.append("姓名:" + person.getName() + ",id:"
                            + person.getId() + ",年龄:" + person.getAge() + ";    ");

                }
                tv.setText(sb.toString());

            }
        });

        tv = (TextView) findViewById(R.id.tv);

    }

}
View Code

最后程序运行如下:

作者:af74776
文章出处:http://www.cnblogs.com/scetopcsa/
欢迎关注微信公众号:yilu_yiyou(一路一游),一个不仅仅是代码的世界!
如果文中有什么错误,欢迎指出。以免更多的人被误导。
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
原文地址:https://www.cnblogs.com/scetopcsa/p/3643487.html