xml 文件解析的 3 种方式

作者: uniapp | 来源:发表于2018-02-24 22:37 被阅读0次

    xml 是数据传输的一种格式,Android 中的布局文件、设置文件等都采用它来表示。Android 中对 xml 文件的解析也有多种方式,下面介绍常用的 3 种方式: Dom 、 SAX 和 dom4j。

    先看一个简单的 xml 文件:

    <?xml version="1.0" encoding="UTF-8" standalone="no"?>
        <书 出版社="骏马">
            <书名>如何成功</书名>
            <作者>uniapp</作者>
            <售价>666</售价>
        </书>
        <书>
            <书名>如何成功1</书名>
            <作者>uniapp</作者>
            <售价>1991</售价>
        </书>
    </书架>
    
    1 Dom解析方式

    Dom 解析通过 Document 类将整个 xml 文件一次读入内存,然后通过操作 Document 实例的属性实现对 xml 文件中元素的增删改查,具体代码如下:

    /**
         * 查看所有元素名称
         * */
        private void printAllElement(Node node){
            if (Node.ELEMENT_NODE==node.getNodeType()){
                System.out.println(node.getNodeName());
            }
            NodeList ns = node.getChildNodes();
            for (int i = 0; i < ns.getLength(); i++) {
                node = ns.item(i);
                printAllElement(node);
            }
        }
    
        /**
         * 更新元素
         * */
        private void updateElement() throws ParserConfigurationException, SAXException, IOException, TransformerException {
            Document doc = getDocument();
            NodeList ns = doc.getElementsByTagName("售价");
            Element el = (Element) ns.item(0);
            el.setTextContent("666");
            writeBackToXml(doc);
        }
    
        /**
         * 删除节点
         * */
        private void deleteElement() throws ParserConfigurationException, SAXException, IOException, TransformerException {
            Document doc = getDocument();
            NodeList ns = doc.getElementsByTagName("售价");
            for (int i = 0; i < ns.getLength(); i++) {
                Node node = ns.item(i);
                if ("111".equals(node.getTextContent())){
                    node.getParentNode().removeChild(node);
                }
    
            }
            writeBackToXml(doc);
        }
        /**
         * 插入元素节点
         * */
        private void addElement() throws ParserConfigurationException, SAXException, IOException, TransformerException {
            Document doc = getDocument();
            NodeList nl = doc.getElementsByTagName("书");
            int l = nl.getLength();
            System.out.print("\n长度" + l + "\n");
            Node n = nl.item(0);
            Element element = doc.createElement("售价");
            element.setTextContent("888");
            n.appendChild(element);
            writeBackToXml(doc);
        }
        /**
         * 将 Doc 写入新文件
         * */
        private void writeBackToXml(Document doc) throws TransformerException {
            TransformerFactory factory = TransformerFactory.newInstance();
            Transformer transformer =  factory.newTransformer();
            transformer.transform(new DOMSource(doc), new StreamResult("./app/src/main/java/test/DTD.xml"));
        }
    /**
         * 获取 Doc 对象
         * */
        private Document getDocument() throws ParserConfigurationException, SAXException, IOException {
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            DocumentBuilder build = factory.newDocumentBuilder();
            Document document = build.parse("./app/src/main/java/test/DTD.xml");
            return document;
        }
    
    2 SAX解析

    SAX 对 xml 文件采用边读边解析的方式,就像我们用眼睛读文章一样,一行一行的进行。相比 Dom 方式产生的瞬时内存峰值,SAX 对内存的消耗比较平稳。它通过解析类提供对外接口,具体实现:

    public class SaxDemo {
        @Test
        public void main() throws ParserConfigurationException, SAXException, IOException{
            //工厂类实例
            SAXParserFactory fac =  SAXParserFactory.newInstance();
            //创建解析器
            SAXParser parser =  fac.newSAXParser();
            //解析文档
            XMLReader reader = parser.getXMLReader();
            reader.setContentHandler(new MyDefultHandle());
            reader.parse("./app/src/main/java/test/DTD.xml");
    
        }
    }
    
    class MyDefultHandle extends DefaultHandler{
    
        @Override
        public void startDocument() throws SAXException {
            super.startDocument();
    
            System.out.println("文档开始");
        }
    
        @Override
        public void endDocument() throws SAXException {
            super.endDocument();
            System.out.println("文档结束");
        }
    
        private boolean isPrice = false;
        @Override
        public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
            super.startElement(uri, localName, qName, attributes);
            System.out.println("元素开始: " + qName);
    
        }
    
        @Override
        public void endElement(String uri, String localName, String qName) throws SAXException {
            super.endElement(uri, localName, qName);
    
            if ("售价".equals(qName)){
                isPrice = false;
            }
            System.out.println("元素结束: " + qName);
    
        }
    
        @Override
        public void characters(char[] ch, int start, int length) throws SAXException {
            super.characters(ch, start, length);
            if (isPrice){
                System.out.println("内容: " + new String(ch, start, length));
            }
        }
    }
    
    3 Dom4j 解析

    Dom4j 解析是第三开源库给出的解析方式,结合了 Dom 和 SAX 双方的优点,对 xml 文件逐步读入内存,并且可以采用面向对象的方式访问节点。代码如下:

    /**
         * 读取属性值
         * */
        public void readAttr() throws DocumentException {
            Document doc = getDocument();
            List<Element> list = doc.getRootElement().elements("书");
            for (int i = 0; i < list.size(); i++) {
                Element el = (Element) list.get(i);
                Attribute att = el.attribute("出版社");
                System.out.print("结果: " + att.getName() + att.getValue());
            }
        }
    
        /**
         * 读取节点
         * */
        public void read() throws DocumentException {
            /**
             * 不能越级获取值
             * */
            Document doc = getDocument();
            org.dom4j.Element el = doc.getRootElement();
            Element firstEl = el.element("书");
            Element firstBookEl = firstEl.element("书名");
    
            String name = firstBookEl.getText();
            System.out.println("书名: " + name);
        }
    
        public void update() throws DocumentException, IOException {
            Document doc = getDocument();
            List<Element> list = doc.getRootElement().elements("书");
            Element element = list.get(0);
            Element priceEl = element.element("售价");
            priceEl.setText("888元");
            XMLWriter writer = new XMLWriter(new FileOutputStream("./app/src/main/java/test/Dom4j3.xml"));
            writer.write(doc);
        }
    
        /**
         * 删除节点
         * */
        public void deletePrice() throws Exception{
            SAXReader reader = new SAXReader();
            Document doc = reader.read("./app/src/main/java/test/Dom4j1.xml");
            Element el = (Element) doc.getRootElement().elements("书").get(1);
            Element elPrice = (Element) el.elements("售价").get(1);
            elPrice.getParent().remove(elPrice);
            XMLWriter writer = new XMLWriter(new FileOutputStream("./app/src/main/java/test/Dom4j2.xml"));
            writer.write(doc);
            writer.close();
        }
        /**
         * 增加节点
         * */
        public void  addEl() throws DocumentException, IOException {
            Document doc = getDocument();
            Element el = (Element) doc.getRootElement().elements("书").get(1);
            el.addElement("售价").setText("6.66元");
            XMLWriter writer = new XMLWriter(new FileOutputStream("./app/src/main/java/test/Dom4j1.xml"));
            writer.write(doc);
            writer.close();
        }
    
        private Document getDocument() throws DocumentException {
            SAXReader reader = new SAXReader();
            return reader.read("./app/src/main/java/test/DTD.xml");
        }
    

    结合以上三种解析方式的特点,我们可以得出结论:如果 xml 文件很小,可以选择面向对象的 Dom 或者 dom4j 方式;反之可以选择 SAX 方式,一面实际内存不足造成闪退。

    喜欢和关注都是对我的鼓励和支持~

    相关文章

      网友评论

        本文标题:xml 文件解析的 3 种方式

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