我爱编程Android知识Android开发经验谈

xml 文件解析的 3 种方式

2018-02-24  本文已影响0人  uniapp

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 方式,一面实际内存不足造成闪退。

喜欢和关注都是对我的鼓励和支持~
上一篇 下一篇

猜你喜欢

热点阅读