XML解析(三),PULL解析XML

来源:互联网 发布:电商网站php 编辑:程序博客网 时间:2024/05/22 03:14

昨天写了【XML解析(一)】SAX解析XML 和【XML解析(二)】DOM解析XML两篇文章,有兴趣的朋友可以去看一下,今天我们来学习一下PULL解析XML,刚好可以跟SAX和DOM解析XML的两种方式对比学习,其实Android里面解析XML最常用的也就这三种,而这三种并不一定拘泥于Android开发,同样也可以用在J2EE开发中,下面我们进入本篇文章的学习。

一、概述

 PULL?,拉?,肯定不是什么的简称了,PULL是Android内置的解析XML的方式,但是并不局限与Android,也可以是J2EE。
 PULL解析具有与SAX类似的特点,提供了与SAX类似的事件,比如:开始元素事件和结束元素事件,看过【XML解析(一)】SAX解析XML 的朋友或者使用过SAX解析XML的朋友是否还记得SAX解析的几个重要的事件吗?这里我简单复习一下SAX的几个重要的事件

SAX的几个重要的事件

  1. startDocument():XML文档解析开始的时候触发,只会调用一次,我们可以在这里做一些解析前的准备工作
  2. startElement():元素或标签解析开始的时候触发
  3. characters:startElement触发后立即触发
  4. endElement():元素或标签解析结束的时候触发
  5. endDocument():XML文档解析结束后触发,只会触发一次

PULL的事件(仅有五个)

  1. START_DOCUMENT:开始文档解析
  2. START_TAG:解析元素
  3. TEXT:解析文本
  4. END_TAG:结束元素解析
  5. END_DOCUMENT:结束文档解析

下面做个事件的简单对比(类似)

PULL SAX START_DOCUMEN startDocument START_TAG startElement TEXT characters END_TAG endElement END_DOCUMENT endElement


 Pull只有一个重要的事件next()

PULL解析XML的优点:

  • 解析速度快
  • 占用内存小,消耗的资源少
  • 简单,易集成(Android)
  • 支持生成,修改,删除XML文件

PULL解析适用于:

  • Android
  • 速度快,效率高的J2EE

大概了解了pull,下面我们通过一个简单的Demo简单学习一下pull 解析 xml

二、PULL解析XML实战

 新建一个Android项目PullParseXmlDemo,因为android集成pull,无需导入jar包,为了方便这里将整个demo的目录结构给出,在文章末尾将会把demo贴上,方便大家下载导入eclipse测试。

目录结构:

这里写图片描述

PULL解析步骤:

  1. 加载xml资源
  2. 得到pull解析器XmlPullParser
  3. 使用解析器解析

1、新建xml测试文件,uses.xml

<?xml version="1.0" encoding="UTF-8"?><users>    <user id="1">        <name>毕向东</name>        <password>bxd123</password>    </user>    <user id="2">        <name>韩顺平</name>        <password>hsp123</password>    </user>    <user id="3">        <name>马士兵</name>        <password>msb123</password>    </user></users>

2、新建JavaBean,User.java

package com.example.pullparsexmldemp;public class User{    private long id;    private String name;    private String password;    public long getId() {        return id;    }    public void setId(long id) {        this.id = id;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public String getPassword() {        return password;    }    public void setPassword(String password) {        this.password = password;    }}

3、新建一个解析核心方法getUsers()封装到一个工具类中,XmlParseUtils.java

public static List<User> getUsers() throws Exception {        List<User> users = null;        User user = null;        // 加载xml资源        InputStream is = XmlParseUtils.class.getClassLoader()                .getResourceAsStream("users.xml");        // 得到Pull解析器        XmlPullParser pullParser = Xml.newPullParser();        // 设置Xml输入流        pullParser.setInput(is, "utf-8");        int event = pullParser.getEventType(); // 触发第一个事件        while (event != XmlPullParser.END_DOCUMENT) {            switch (event) {                case XmlPullParser.START_DOCUMENT:                    Log.e(TAG, pullParser.getName()+"----START_DOCUMENT");                    users = new ArrayList<User>();                    break;                case XmlPullParser.START_TAG:                    if ("user".equals(pullParser.getName())) {                        Log.e(TAG, pullParser.getName()+"----START_TAG");                        user = new User();                        int id = Integer.valueOf(pullParser.getAttributeValue(0));                        user.setId(id);                    }                    if (user != null) {                        if ("name".equals(pullParser.getName())) {                            Log.e(TAG, pullParser.getName()+"----START_TAG");                            // 注意是nextText()取标签之间的文本,而不是getText()                            // getText()返回的是当前触发事件的字符描述                            user.setName(pullParser.nextText());                        }                        if ("password".equals(pullParser.getName())) {                            Log.e(TAG, pullParser.getName()+"----START_TAG");                            user.setPassword(pullParser.nextText());                        }                    }                    break;                case XmlPullParser.END_TAG:                    if ("user".equals(pullParser.getName())) {                        Log.e(TAG, pullParser.getName()+"----END_TAG");                        users.add(user);                        user = null;                    }                    break;                }            event = pullParser.next();        }        if(event == XmlPullParser.END_DOCUMENT){            Log.e(TAG, pullParser.getName()+"----END_DOCUMENT");        }        return users;    }

 这里的解析过程和SAX解析过程非常类似,就不多说了,这里先将日志打印,方便我们下面分析pull解析原理。

OK,PULL解析XML的核心就在getUsers()方法中了,接下来是测试是否解析成功了

Android的单元测试:

参考:【XML解析(一)】SAX解析XML

测试结果:

这里写图片描述

OK,可以看到使用PULL成功解析XML,下面我们看一下下面的日志来简单分析一下PULL解析的过程:

这里写图片描述

 可以看到,当文档解析开始的时候START_DOCUMENT事件触发,仅触发了一次,接下来没遇到一个新的标签的开始都触发了STAET_TAG时间,每个标签的结束都触发了END_TAG,所以START_TAGEND_TAG事件触发的次数和标签是成对出现的,即有开始就有结束,最后文档解析结束END_DOCUMENT触发。原理过程分析结束,前面我们说了PULL不仅可以解析XML,还可以生成,修改,删除XML。下面我们通过PULL生成XML做个测试

三、PULL生成XML

PULL生成XML步骤:

  1. 设置输出源
  2. 得到xml序列化类xmlSerializer
  3. 使用序列化类生成XML

第一步:在工具类中添加一个方法createXml(List users,OutputStream outputStream)

        XmlSerializer xmlSerializer = Xml.newSerializer();        // 设置输出源及编码        xmlSerializer.setOutput(outputStream,"utf-8");        // 参数1:设置编码        // 参数2:standalone  用来表示该文件是否呼叫其它外部的文件。若值是 true         //      表示没有呼叫外部文件,若值是 false 则表示有呼叫外部文件。默认值是true        xmlSerializer.startDocument("utf-8", true);        // 生成users开始标签        xmlSerializer.startTag(null, "users");        for(User user : users){ // 每循环一次生成一个user            // 生成user标签和id属性            xmlSerializer.startTag(null, "user");            xmlSerializer.attribute(null, "id", user.getId()+"");            // 生成name开始标签            xmlSerializer.startTag(null, "name");            // 设置name标签的文本            xmlSerializer.text(user.getName());            // 闭合name标签            xmlSerializer.endTag(null, "name");            // ...            xmlSerializer.startTag(null, "password");            xmlSerializer.text(user.getPassword());            xmlSerializer.endTag(null, "password");            // 闭合user标签            xmlSerializer.endTag(null, "user");        }        xmlSerializer.endTag(null, "users"); // 闭合users标签        xmlSerializer.endDocument(); // 结束文档        outputStream.flush(); // 将所有缓冲区的数据全部写到文件中        outputStream.close(); // 一定不要忘了关闭流    }

 注释说的差不多了,是不是觉得PULL生成XML文件好简单。

说明:startDocument的两个参数分别设置生成的xml文件头部的encoding和standalone属性,下面我们看了生成的文件就知道了。

第二步、在PullParseXmlTest.java中添加一个测试方法testCreateXml()

/**     * 测试生成xml     * @throws Exception     */    public void testCreateXml() throws Exception{        // this.getContext().getFilesDir()得到的是/data/data/files/        File file = new File(this.getContext().getFilesDir(),"users.xml");        FileOutputStream fileOutputStream = new FileOutputStream(file);        List<User> users = new ArrayList<User>();        User user1 = new User();        user1.setId(1);        user1.setName("毕向东");        user1.setPassword("bxd123");        users.add(user1);        User user2 = new User();        user2.setId(2);        user2.setName("韩顺平");        user2.setPassword("hsp123");        users.add(user2);        User user3 = new User();        user3.setId(3);        user3.setName("马士兵");        user3.setPassword("msb123");        users.add(user3);        XmlParseUtils.createXml(users, fileOutputStream);    }

 没什么好说的,直接运行测试

下面我们看看生成的users.xml文件

1、打开DDMS视图:

这里写图片描述

2、找到当前应用的files文件夹

这里写图片描述

3、将生成的xml导出

这里写图片描述

 这里也可以用adb pull [remote] [local]:命令文件

adb命令参考:adb常用命令

用编辑器打开users.xml可以看到(格式化后):

<?xml version='1.0' encoding='utf-8' standalone='yes' ?><users>    <user id="1">        <name>毕向东</name>        <password>bxd123</password>    </user>    <user id="2">        <name>韩顺平</name>        <password>hsp123</password>    </user>    <user id="3">        <name>马士兵</name>        <password>msb123</password>    </user></users>

 注意看xml文件头,encodingstandalone属性都是startDocument()的两个参数知道指定的

<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
  • 关于PULL,SAX,DOM解析XML
     PULL解析XML与SAX类似,具有解析速度快,效率高,占用资源少的特点,而DOM解析XML虽然简单,可以随机访问文档树的任何一个节点,可以知道整个文档树结构和整个文档树的所有信息,但正是由于在内存中要形成这样的一个文档树,所以导致了解析速度慢,占用资源大,这对于资源多,不要求效率的场合是一种不错的选择,但是对于Android等内存小,cpu资源宝贵的移动设备来说是致命的,SAX虽然速度快,占用资源,但由于无法修改,生成XML,所以这就是为什么Android集成PULL,而不是SAX和DOM的原因吧。

总结:XML解析,生成,修改XML都好简单,Android集成PULL,掌握PULL必须的。

上面这篇文章由于个人理解,如果有理解错的地方,欢迎指出,与君共勉,一起进步。

demo下载地址:http://download.csdn.net/detail/ydxlt/9330427

0 0
原创粉丝点击