美文网首页
Andorid XML三种解析方式和优缺点

Andorid XML三种解析方式和优缺点

作者: 梦星夜雨 | 来源:发表于2020-06-09 11:30 被阅读0次

    前言

    Andorid XML有SAX, DOM, Pull三种解析方式。本文以下面的xml为例。
    <?xml version="1.0" encoding="UTF-8"?>

    <?xml version="1.0" encoding="UTF-8"?>
    <students>
        <student>
            <name>张三</name>
            <studentId>12</studentId>
            <score>67</score>
        </student>
        <student>
            <name>李四</name>
            <studentId>13</studentId>
            <score>79</score>
        </student>
        <student>
            <name>王五</name>
            <studentId>14</studentId>
            <score>92</score>
        </student>
    </students>
    

    1.SAX解析

    SAX(Simple API for XML)解析器是一种基于事件的解析器,从文件的开始顺序解析到文档的结束,不可暂停或倒退。

    • 优点:解析速度快,占用内存少。
    • 缺点:不会记录标签的关系,而要让你的应用程序自己处理,增加程序负担。

    新建XMLContentHandler类继承DefaultHandler,重写startDocument,startElement,characters,endElement方法。只需要传入InputStream即可,代码如下:

    package com.xml.test;
    
    import org.xml.sax.Attributes;
    import org.xml.sax.SAXException;
    import org.xml.sax.helpers.DefaultHandler;
    
    import java.util.ArrayList;
    import java.util.List;
    
    public class XMLContentHandlerStudent extends DefaultHandler {
    
        private List<Student> students = null;
        private Student currentStudent;
        private String tagName = null;//当前解析的元素标签
    
     public static List<Student> readXmlBySAX(InputStream inputStream) {
            try {
                /**【创建解析器】**/
                SAXParserFactory spf = SAXParserFactory.newInstance();
                SAXParser saxParser = spf.newSAXParser();
                XMLContentHandlerStudent handler = new XMLContentHandlerStudent();
                saxParser.parse(inputStream, handler);
                inputStream.close();
                return handler.getStudents();
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }
    
        public List<Student> getStudents() {
            return students;
        }
    
        /**文档开始时,调用此方法**/
        @Override
        public void startDocument() throws SAXException {
            students = new ArrayList<>();
        }
    
        /**
         * 标签开始时,调用此方法
         * uri 命名空间|localName是不带命名空间前缀的标签名|
         * qName 带命名空间前缀的标签名|
         * attributes 可以得到所有的属性名和对应的值
         **/
        @Override
        public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
            if (localName.equals("student")) {
                currentStudent = new Student();
    //            currentStudent.setId(Integer.parseInt(attributes.getValue("id")));
            }
            this.tagName = localName;
        }
    
        /**
         * 接收标签中字符数据时,调用此方法
         * ch 存放标签中的内容,
         * start 起始位置,
         * length 内容长度
         **/
        @Override
        public void characters(char[] ch, int start, int length) throws SAXException {
            if (tagName != null) {
                String data = new String(ch, start, length);
                if (tagName.equals("name")) {
                    this.currentStudent.setName(data);
                } else if (tagName.equals("studentId")) {
                    this.currentStudent.setStudentId(Short.parseShort(data));
                } else if (tagName.equals("score")) {
                    this.currentStudent.setScore(Short.parseShort(data));
                }
            }
        }
        /**
         * 标签结束时,调用此方法
         * localName 表示元素本地名称(不带前缀)
         * qName 表示元素的限定名(带前缀)
         **/
        @Override
        public void endElement(String uri, String localName, String qName) throws SAXException {
            if (localName.equals("student")) {
                students.add(currentStudent);
                currentStudent = null;
            }
            this.tagName = null;
        }
    }
    

    2.DOM解析

    DOM(Document Object Model)是将其转换为一个对象模型的集合,用树这种数据结构对信息进行储存,通过DOM接口,应用程序可以在任何时候访问xml文档中的任何一部分数据。

    • 优点:易用性强,使用DOM时,将把所有的XML文档信息都存于内存中,并且遍历简单,支持XPath,增强了易用性。
    • 缺点:效率低,解析速度慢,内存占用量过高,对于大文件来说几乎不可能使用。
    public static List<Student> readXmlByDOM(InputStream inputStream){
            List<Student> students = new ArrayList<>();
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            try {
                DocumentBuilder builder = factory.newDocumentBuilder();
                Document dom = builder.parse(inputStream);
                Element rootElement = dom.getDocumentElement();
                NodeList items = rootElement.getElementsByTagName("student");
                for (int i = 0; i < items.getLength(); i++) {
                    Element elementItem = (Element) items.item(i);
                    NodeList childsNodes = elementItem.getChildNodes();
                    Student student = new Student();
                    for (int j = 0; j < childsNodes.getLength(); j++) {
                        Node node = (Node) childsNodes.item(j);
                        // 判断是否为元素类型
                        if(node.getNodeType() == Node.ELEMENT_NODE){
                            Element childNode = (Element) node;
                            String nodeName = childNode.getNodeName();
                            // 判断对应元素
                            if ("name".equals(childNode.getNodeName())) {
                                student.setName(childNode.getFirstChild().getNodeValue());
                            }else if("studentId".equals(childNode.getNodeName())){
                                student.setStudentId(Integer.parseInt(childNode.getFirstChild().getNodeValue()));
                            } else if ("score".equals(childNode.getNodeName())) {
                                student.setScore(Integer.parseInt(childNode.getFirstChild().getNodeValue()));
                            }
                        }
                    }
                    students.add(student);
                }
                inputStream.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
            return students;
        }
    

    3.Pull解析

    Pull解析与SAX解析原理上类似,但提供了开始,结束元素,并且提供了NEXT方法主动提取。在移动端而言,Pull解析最优。

    public static List<Student> readXmlByPull(InputStream inputStream) {
            XmlPullParser parser = Xml.newPullParser();
            try {
                parser.setInput(inputStream, "UTF-8");
                int eventType = parser.getEventType();
    
                Student currenStudent = null;
                List<Student> students = null;
    
                while (eventType != XmlPullParser.END_DOCUMENT) {
                    switch (eventType) {
                        case XmlPullParser.START_DOCUMENT: // 文档开始事件
                            students = new ArrayList<>();
                            break;
                        case XmlPullParser.START_TAG: // 元素(即标签)开始事件
                            String name = parser.getName();
                            if (name.equals("student")) {
                                currenStudent = new Student();
                            } else if (currenStudent != null) {
                                // 判断标签名(元素名)
                                if (name.equals("name")) {
                                    currenStudent.setName(parser.nextText());
                                } else if (name.equals("studentId")) {
                                    currenStudent.setStudentId(Integer.valueOf(parser.nextText()));
                                } else if (name.equals("score")) {
                                    currenStudent.setScore(Integer.valueOf(parser.nextText()));
                                }
                            }
                            break;
                        case XmlPullParser.END_TAG:// 元素结束事件
                            if (parser.getName().equalsIgnoreCase("student") && currenStudent != null) {
                                students.add(currenStudent);
                                currenStudent = null;
                            }
                            break;
                    }
                    eventType = parser.next();
                }
                inputStream.close();
                return students;
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }
    

    相关文章

      网友评论

          本文标题:Andorid XML三种解析方式和优缺点

          本文链接:https://www.haomeiwen.com/subject/cetdtktx.html