XML数据的三种解析方式

女生的网名这么多〃 提交于 2019-12-18 07:06:30

Android开发主流是传json,而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解析器的工作方式为允许你的应用程序代码主动从解析器中获取事件,正因为是主动获取事件,因此可以在满足了需要的条件后不再获取事件,结束解析。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!