Android XML解析之PULL解析 简单示例讲解

上一篇文章用一个简单例子讲了下SAX方式解析XML文件的用法及特点,可点击查看:
Android XML文件解析之SAX解析 简单示例讲解

本篇文章,我们接着用个简单例子展示一下PULL方式解析XML。

先介绍下PULL方式解析XML的特点,它和SAX方式的相同之处是都是事件驱动的流式解析方式,一边读取XML内容一边解析,不可暂停或者倒退,直到结束。效率高,占用内存小。

而和SAX解析的不同点在于,PULL解析过程中并不会触发方法回调,而是会产生类似“开始新节点”,“结束一个节点”这样的事件,用数字表示。我们需要对这些事件做判断处理。

另外,Android系统本身使用到的各种xml文件,其内部也是采用Pull解析器进行解析的。

接下来是实例,前面两步准备工作和上一篇SAX解析的一样:

一、先准备一个简单的xml文件。

路径:res/raw/person_data.xml:

<?xml version="1.0" encoding="UTF-8"?>
<data>
    <person id="5">
        <name>Jack</name>
        <age>25</age>
    </person>
    <person id="20">
        <name>Rose</name>
        <age>80</age>
    </person>
</data>
二、新建一个Person类。

我们的目标是把上面的xml数据(两个person)转换成一个Person列表。
Person类如下,和xml里的属性一一对应:

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

    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }

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

下面先看看如何用PULL方式解析上面的xml:

三、得到PULL解析器

PULL方式解析xml,就不用自定义解析器了,可以使用现有的类得到解析器。

这里介绍两种PULL解析器,XmlPullParser和XmlResourceParser,其中后者是前者的子类。
1、XmlPullParser解析器:

    public static XmlPullParser getXmlPullParser(Context context) {
        XmlPullParser pullParser = null;
        try {
            // 创建Pull解析器
            XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
            pullParser = factory.newPullParser();
            // 设置xml数据源
            InputStream inputStream = context.getResources().openRawResource(R.raw.person_data);
            pullParser.setInput(new InputStreamReader(inputStream));
        } catch (XmlPullParserException e) {
            e.printStackTrace();
        }
        return pullParser;
    }

2、XmlResourceParser解析器:
这种方式更加简单,

XmlResourceParser pullParser = context.getResources().getXml(R.xml.person_data);

但是注意这种方式,xml文件需要放到res/xml文件夹下才行。
然后下面是解析的实现。

四、PULL方式解析实现

把第三步得到的 pullParser 传入下面的方法中运行即可得到解析结果。

    public static void pullParseXml(XmlPullParser pullParser) {
        List<Person> personList = null; // 存储最终得到的结果
        Person person = null; // 当前正在解析的Person
        try {
            int eventType = pullParser.getEventType();
            // 开始解析。如果解析遇到的事件是文件解析结束的话就退出循环
            while (eventType != XmlPullParser.END_DOCUMENT) {
                String currentNodeName = pullParser.getName();
                switch (eventType) {
                    case XmlPullParser.START_DOCUMENT:
                        // 开始解析,可以在这里做一些初始化
                        personList = new ArrayList<>();
                        Log.d(TAG, "START_DOCUMENT: node == " + currentNodeName);
                        break;
                    case XmlPullParser.START_TAG:
                        // 开始解析某个节点
                        if (currentNodeName.equals("person")) {
                            // 开始节点是“person”,则开始一个新Person的解析
                            person = new Person();
                            // 获取id属性
                            String idStr = pullParser.getAttributeValue(null, "id");
                            person.setId(Integer.parseInt(idStr));
                        } else if (currentNodeName.equals("name")) {
                            // 获取name
                            person.setName(pullParser.nextText());
                        } else if (currentNodeName.equals("age")) {
                            // 获取age
                            person.setAge(Integer.parseInt(pullParser.nextText()));
                        }
                        Log.d(TAG, "START_TAG: node == " + currentNodeName);
                        break;
                    case XmlPullParser.END_TAG:
                        // 结束某个节点的解析
                        if (currentNodeName.equals("person")) {
                            // 如果person节点结束的话,就把已解析的person对象加入列表
                            personList.add(person);
                        }
                        Log.d(TAG, "END_TAG: node == " + currentNodeName);
                        break;
                    case XmlPullParser.END_DOCUMENT:
                        // 结束文件解析,这里不会走到,因为我们把它作为while循环的终止条件
                        break;
                    default:
                        break;
                }
                // 继续解析下一个事件
                eventType = pullParser.next();
            }
        } catch (XmlPullParserException e) {
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 打印最终结果
        Log.d(TAG, "personList == " + personList);
    }

运行结果:

personList == [Person{id=5, name='Jack', age=25}, Person{id=20, name='Rose', age=80}]

为了更直观的查看解析过程,我在上面的方法每一步都加上了log,打印log结果如下,可对照查看:

D/TAG: 	START_DOCUMENT: node == null
D/TAG: 	START_TAG: node == data
		START_TAG: node == person
		START_TAG: node == name
		START_TAG: node == age
D/TAG: 	END_TAG: node == person
		START_TAG: node == person
		START_TAG: node == name
D/TAG: 	START_TAG: node == age
		END_TAG: node == person
		END_TAG: node == data

再贴个上一篇的链接,方便对照理解:
Android XML文件解析之SAX解析 简单示例讲解

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值