XML数据的三种解析方式

Android开发主流是传json,而XML解析一般跟网络请求,爬虫数据相关。
Android的开发中,更推荐使用PULL解析XML

一丶概述

在Android中提供了三种解析XML的方式:DOM(Document Objrect Model),SAX(Simple API XML),以及Android推荐的Pull解析方式。

如图:
在这里插入图片描述

SAX(Simple API for XML) 使用流式处理的方式,它并不记录所读内容的相关信息。它是一种以事件为驱动的XML API,解析速度快,占用内存少。使用回调函数来实现。 缺点是不能倒退。

DOM(Document Object Model) 是一种用于XML文档的对象模型,可用于直接访问XML文档的各个部分。它是一次性全部将内容加载在内存中,生成一个树状结构,它没有涉及回调和复杂的状态管理。 缺点是加载大文档时效率低下。

Pull内置于Android系统中。也是官方解析布局文件所使用的方式。Pull与SAX有点类似,都提供了类似的事件,如开始元素和结束元素。不同的是,SAX的事件驱动是回调相应方法,需要提供回调的方法,而后在SAX内部自动调用相应的方法。而Pull解析器并没有强制要求提供触发的方法。因为他触发的事件不是一个方法,而是一个数字。它使用方便,效率高。

SAX、DOM、Pull的比较: 
1. 内存占用:SAX、Pull比DOM要好; 
2. 编程方式:SAX采用事件驱动,在相应事件触发的时候,会调用用户编好的方法,也即每解析一类XML,就要编写一个新的适合该类XML的处理类。DOM是W3C的规范,Pull简洁。 
3. 访问与修改:SAX采用流式解析,DOM随机访问。 
4. 访问方式:SAX,Pull解析的方式是同步的,DOM逐字逐句

这里不做详细讲解,看注释,上代码

看项目文件,注意XML放的位置,不会建assets参考http://blog.csdn.net/u012861467/article/details/51773191


三种解析方式的步骤:

  1. 在Assets文件夹中模拟创建XML数据
  2. 创建对应XML的Bean对象
  3. 开始解析

XML数据的Dom解析

DOM解析XML文件时,会将XML文件的所有内容读取到内存中(内存的消耗比较大),然后允许您使用DOM API遍历XML树、检索所需的数据

一、在Assets文件夹中模拟创建XML文件

<students>
    <student>
        <name sex="man">小明</name>
        <nickName>明明</nickName>
    </student>
    <student>
        <name sex="woman">小红</name>
        <nickName>红红</nickName>
    </student>
    <student>
        <name sex="man">小亮</name>
        <nickName>亮亮</nickName>
    </student>
</students>
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

二、创建对应XML的Bean对象

public class Student {
    private String name;
    private String sex;
    private String nickName;

    public String getName() {
        return name;
    }

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

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public String getNickName() {
        return nickName;
    }

    public void setNickName(String nickName) {
        this.nickName = nickName;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", sex='" + sex + '\'' +
                ", nickName='" + nickName + '\'' +
                '}';
    }
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38

三、Dom解析

InputStream inputStream =  getAssets().open("student.xml");
//获取xml文件
public List<Student> dom2xml(InputStream is) throws Exception {
    //一系列的初始化
    List<Student> list = new ArrayList<>();
    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    DocumentBuilder builder = factory.newDocumentBuilder();
    //获得Document对象
    Document document = builder.parse(is);
    //获得student的List
    NodeList studentList = document.getElementsByTagName("student");
    //遍历student标签
    for (int i = 0; i < studentList.getLength(); i++) {
        //获得student标签
        Node node_student = studentList.item(i);
        //获得student标签里面的标签
        NodeList childNodes = node_student.getChildNodes();
        //新建student对象
        Student student = new Student();
        //遍历student标签里面的标签
        for (int j = 0; j < childNodes.getLength(); j++) {
            //获得name和nickName标签
            Node childNode = childNodes.item(j);
            //判断是name还是nickName
            if ("name".equals(childNode.getNodeName())) {
                String name = childNode.getTextContent();
                student.setName(name);
                //获取name的属性
                NamedNodeMap nnm = childNode.getAttributes();
                //获取sex属性,由于只有一个属性,所以取0
                Node n = nnm.item(0);
                student.setSex(n.getTextContent());
            } else if ("nickName".equals(childNode.getNodeName())) {
                String nickName = childNode.getTextContent();
                student.setNickName(nickName);
            }
        }
        //加到List中
        list.add(student);
    }
    return list;
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40

XML数据的Sax解析

SAX是一个解析速度快并且占用内存少的xml解析器,SAX解析XML文件采用的是事件驱动,它并不需要解析完整个文档,而是按内容顺序解析文档的过程

由于前面一和二的步骤是一样的,这里就省略了

三、Sax解析

public List<Student> sax2xml(InputStream is) throws Exception {
    SAXParserFactory spf = SAXParserFactory.newInstance();
    //初始化Sax解析器
    SAXParser sp = spf.newSAXParser();
    //新建解析处理器
    MyHandler handler = new MyHandler();
    //将解析交给处理器
    sp.parse(is, handler);
    //返回List
    return handler.getList();
}

public class MyHandler extends DefaultHandler {

    private List<Student> list;
    private Student student;
    //用于存储读取的临时变量
    private String tempString;

    /**
     * 解析到文档开始调用,一般做初始化操作
     *
     * @throws SAXException
     */
    @Override
    public void startDocument() throws SAXException {
        list = new ArrayList<>();
        super.startDocument();
    }

    /**
     * 解析到文档末尾调用,一般做回收操作
     *
     * @throws SAXException
     */
    @Override
    public void endDocument() throws SAXException {
        super.endDocument();
    }

    /**
     * 每读到一个元素就调用该方法
     *
     * @param uri
     * @param localName
     * @param qName
     * @param attributes
     * @throws SAXException
     */
    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
        if ("student".equals(qName)) {
            //读到student标签
            student = new Student();
        } else if ("name".equals(qName)) {
            //获取name里面的属性
            String sex = attributes.getValue("sex");
            student.setSex(sex);
        }
        super.startElement(uri, localName, qName, attributes);
    }

    /**
     * 读到元素的结尾调用
     *
     * @param uri
     * @param localName
     * @param qName
     * @throws SAXException
     */
    @Override
    public void endElement(String uri, String localName, String qName) throws SAXException {
        if ("student".equals(qName)) {
            list.add(student);
        }
        if ("name".equals(qName)) {
            student.setName(tempString);
        } else if ("nickName".equals(qName)) {
            student.setNickName(tempString);
        }
        super.endElement(uri, localName, qName);
    }

    /**
     * 读到属性内容调用
     *
     * @param ch
     * @param start
     * @param length
     * @throws SAXException
     */
    @Override
    public void characters(char[] ch, int start, int length) throws SAXException {
        tempString = new String(ch, start, length);
        super.characters(ch, start, length);
    }

    /**
     * 获取该List
     *
     * @return
     */
    public List<Student> getList() {
        return list;
    }
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106

或者:

public class MyHandler extends DefaultHandler {

        private List<Student> list;
        private Student student;
        String name;
        String nickname;
        String sex;
        String local;
        @Override
        public void startDocument() throws SAXException {
            list = new ArrayList<>();
        }
        @Override
        public void endDocument() throws SAXException {
            super.endDocument();
        }

        @Override
        public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
            local = localName;
            if(local.equals("name")){
                sex = attributes.getValue("sex");
            }
            super.startElement(uri, localName, qName, attributes);
        }

        @Override
        public void endElement(String uri, String localName, String qName) throws SAXException {
            if ("student".equals(qName)) {
                student.setName(name);
                student.setNickName(nickname);
                student.setSex(sex);
                list.add(student);
            }
            super.endElement(uri, localName, qName);
        }

        @Override
        public void characters(char[] ch, int start, int length) throws SAXException {
            if ("student".equals(local)) {
                //读到student标签
                student = new Student();
            } else if ("name".equals(local)) {
                //获取name里面的属性
                name = new String(ch, start, length);
            }else if ("nickName".equals(local)) {
                //获取name里面的属性
                nickname = new String(ch, start, length);
            }
            super.characters(ch, start, length);
        }

        public List<Student> getList() {
            return list;
        }
    }

XML数据的Pull解析

Pull解析器的运行方式与 SAX 解析器相似。它提供了类似的事件,可以使用一个switch对感兴趣的事件进行处理

三、Pull解析

public List<Student> pull2xml(InputStream is) throws Exception {
    List<Student> list = null;
    Student student = null;
    //创建xmlPull解析器
    XmlPullParser parser = Xml.newPullParser();
    ///初始化xmlPull解析器
    parser.setInput(is, "utf-8");
    //读取文件的类型
    int type = parser.getEventType();
    //无限判断文件类型进行读取
    while (type != XmlPullParser.END_DOCUMENT) {
        switch (type) {
            //开始标签
            case XmlPullParser.START_TAG:
                if ("students".equals(parser.getName())) {
                    list = new ArrayList<>();
                } else if ("student".equals(parser.getName())) {
                    student = new Student();
                } else if ("name".equals(parser.getName())) {
                    //获取sex属性
                    String sex = parser.getAttributeValue(null,"sex");
                    student.setSex(sex);
                    //获取name值
                    String name = parser.nextText();
                    student.setName(name);
                } else if ("nickName".equals(parser.getName())) {
                    //获取nickName值
                    String nickName = parser.nextText();
                    student.setNickName(nickName);
                }
                break;
            //结束标签
            case XmlPullParser.END_TAG:
                if ("student".equals(parser.getName())) {
                    list.add(student);
                }
                break;
        }
        //继续往下读取标签类型
        type = parser.next();
    }
    return list;
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43

Sax解析与Pull解析区别

SAX和Pull的区别:SAX解析器的工作方式是自动将事件推入事件处理器进行处理,因此你不能控制事件的处理主动结束;而Pull解析器的工作方式为允许你的应用程序代码主动从解析器中获取事件,正因为是主动获取事件,因此可以在满足了需要的条件后不再获取事件,结束解析。


转自:
XML使用SAX解析与PULL解析的区别
https://blog.csdn.net/zhliro/article/details/46831253
在最近的应用中,经常会用到对XML的解析,但是一直有一个疑问就是SAX解析与PULL解析的区别到底是什么。搜索了相关的问题,整理如下,以便大家查询。

我们知道,SAX解析是事件驱动的,它不会将整个文档读入内存再解析,而是在读取文档的过程中就解析它,所以,文档读入的过程也就是SAX解析的过程。

虽然SAX方式解析XML不会将整个文档放入内存,但它还是会遍历完毕文档中所有的节点。

那么,当我们在解析XML文件时,如果只需要文档前边或是中间一小部分数据,使用SAX解析就浪费了处理器资源,这时我们使用PULL解析就非常合适了。

SAX是一种基于“推”的解析方式,这种解析方法速度快、占用内存少,但是它需要应用程序自己处理解析器的状态,实现起来会比较麻烦,而且它只支持对XML文件的读取,不支持写入。“推”到底是怎么回事呢?SAX解析器的工作方式是自动将事件推入注册的事件处理器进行处理,因此我们不能控制事件的处理主动结束。

PULL则是一种基于“拉”的解析方式,即应用程序根据自己的需要控制解析器的读取。这种方式继承了SAX解析速度快、占用内存少等优点,同时它也保持了接口简单、编程容易等特点。“拉”又是怎么回事呢?PULL解析器的工作方式为允许应用程序代码主动从解析器中获取事件,正因为是主动获取事件,因此可以在满足了需要的条件后不再获取事件,结束解析。

使用SAX解析,在解析器解析过程中通过回调把TAB/VALUE值等传给我们,我们可以直接拿到这些值进行比较、处理。而PULL的原理是它只告诉我们一个TAG开始或者结束了,至于TAG/VALUE的值是什么需要我们自己去向解析器问,所以叫做PULL(拉),而SAX看起来是PUSH(推)给我们的。

其实再从我们之前的例子中也可以看出SAX与PULL之间的区别,PULL是使用一个循环结构,循环体中我们可以随时跳出(break),而SAX不是,SAX是只要开始解析了,就必须解析完成。所以PULL的使用比SAX会更加灵活,在Android的开发中,更推荐使用PULL解析XML。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值