Java解析XML的四种方式简单对比
四种方式各有各的特点,下面简单归纳对比一下。

DOM方式:
优点:
(1) 能随意操作文档的任意一个位置不依赖于平台
(2) 其他部分平台也能够使用
(3) 双向操作,解析的同时支持修改
(4) 树形层级结构,和文档一一对应,编写代码简单

缺点:
(1) 解析前要将整个文档加载到内存构建关系层次,比较耗资源
(2)由于是加载整个文件,所以耗时较多


SAX方式:
优点:
(1)基于事件驱动模型,事件丰富
(2)逐条解析,耗费资源少
(3)速度快

缺点:
(1)在Handler中处理事件,事件丰富的同时给存储实体带来了不便
(2)单向解析,无法获取文档内任意位置,即便只是需要文档内的一个属性,也需要从头开始解析


JDOM方式:
优点:
(1)优化了DOM API
(2)纯JAVA实现, 方便JAVA开发人员使用

缺点:
(1)性能较差

DOM4j方式:
优点:
(1)支持XPath,可直接定位选取节点或节点集
(2)各方面表现优秀
(3)合并了许多超出基本XML文档表示的功能。


下面简单地写一个例子对比一下四种解析方式的速度(只是简单进行测试,仅供参考。示例代码中均屏蔽了输出):
DOM.java:
package org.devsong.xmlload;

import java.io.File;
import java.io.IOException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

public class DOM {
    /**
     * 获取DocumentBuilder对象
     */
    public DocumentBuilder getDocumentBuilder() {
        // 通过DocumentBuilderFactory的静态方法获取实例
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = null;
        try {
            builder = factory.newDocumentBuilder();
        } catch (ParserConfigurationException e) {
            e.printStackTrace();
        }
        return builder;
    }

    /**
     * 开始解析
     */
    public void startParse(String uri) {
        try {
            Document document = getDocumentBuilder().parse(new File(uri));
            Element root = document.getDocumentElement(); // 根节点
            // 调用parseNode方法开始递归解析
            parseNode(root);

        } catch (SAXException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 递归解析每一个节点
     */
    public void parseNode(Node root) {
        if (root == null)
            return;
        String nodeName = root.getNodeName();

        // 输出节点名
        //System.out.print(nodeName + ":");

        // 获取当前节点的所有属性
        NamedNodeMap nodeMap = root.getAttributes();
        if (nodeMap != null) {
            for (int i = 0; i < nodeMap.getLength(); i++) {
                Node node = nodeMap.item(i);
                // 输出属性信息
                //System.out.print("[attr]" + node.getNodeName() + ":" + node.getNodeValue() + "   ");
            }
        }

        // 剔除冗余内容:空格和换行
        // 在避免空指针异常的情况下如果当前获得的节点文本经过trim()之后不为空,则输出当前节点内容
        if (root.getFirstChild() != null && root.getFirstChild().getNodeValue() != null
                && !(root.getFirstChild().getNodeValue()).trim().equals("")) {
            String nodeValue = root.getFirstChild().getNodeValue();
            //System.out.print(nodeValue + "   ");
        }

        // 获取当前节点的所有子节点
        NodeList nodeList = root.getChildNodes();
        if (nodeList != null) {
            for (int i = 0; i < nodeList.getLength(); i++) {
                Node node = nodeList.item(i);
                // 剔除冗余节点(空文本段)
                if (node.getNodeType() != Node.TEXT_NODE) {
                    // 进行递归解析每一个节点
                    parseNode(node);
                }
            }
        }
    }
}

JDOM.java:
package org.devsong.xmlload;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.List;

import org.jdom2.Attribute;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;

public class JDOM {
    /**
     * 获取Document对象
     * 
     * @param uri
     * @return
     */
    private Document getDocment(String uri) {
        // 获取SAXBuilder
        SAXBuilder builder = new SAXBuilder();
        File file = new File(uri);
        Document doc = null;
        try {
            doc = builder.build(new FileInputStream(file));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (JDOMException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return doc;
    }

    /**
     * 开始解析
     */
    public void startParse(String uri) {
        // 获取根节点,从根结点开始解析
        Element ele = getDocment(uri).getRootElement();
        parseNode(ele);
    }

    /**
     * 节点递归解析
     * 
     * @param node
     */
    private void parseNode(Element node) {
        
        //System.out.print(node.getName() + ":");

        // 获取节点属性列表
        List attrList = node.getAttributes();
        if (attrList != null) {
            // 解析所有属性
            for (int i = 0; i < attrList.size(); i++) {
                Attribute attr = attrList.get(i);
                //System.out.print("[attr]" + attr.getName() + ":" + attr.getValue() + "   ");
            }
        }

        // 剔除空白文本
        // 输出节点内容
        if (node.getText() != null && !node.getText().trim().equals("")) {
            //System.out.print(node.getText() + "   ");
        }

        // 得到子节点列表,进行递归解析
        List childList = node.getChildren();
        if (childList != null) {
            for (int i = 0; i < childList.size(); i++) {
                Element child = childList.get(i);
                parseNode(child);
            }
        }
    }
}

SAX.java:
package org.devsong.xmlload;

import java.io.IOException;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.devsong.myhandler.MyHandler;
import org.xml.sax.SAXException;

public class SAX {
    public void startParse(String uri) {
        try {
            SAXParserFactory factory = SAXParserFactory.newInstance();
            SAXParser parser = factory.newSAXParser();
            MyHandler handler = new MyHandler();
            parser.parse(uri, handler);
        } catch (ParserConfigurationException e) {
            e.printStackTrace();
        } catch (SAXException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

SAX需要的 MyHandler.java:
package org.devsong.myhandler;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

public class MyHandler extends DefaultHandler {

    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
        super.startElement(uri, localName, qName, attributes);
        //System.out.print(qName + ":");
        if (attributes != null) {
            for (int i = 0; i < attributes.getLength(); i++) {
                //System.out.print("[attr]" + attributes.getQName(i) + ":" + attributes.getValue(i) + "   ");
            }
        }
    }

    @Override
    public void characters(char[] ch, int start, int length) throws SAXException {
        super.characters(ch, start, length);
        String ContentTemp = new String(ch, start, length);
        if (!"".equals(ContentTemp.trim())) {
            //System.out.print(ContentTemp + "   ");
        }
    }
}

Dom4j: Dom4j.java
package org.devsong.xmlload;

import java.io.File;
import java.util.List;

import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

public class Dom4j {
    
    public void startParse(String uri) {
        //获取SAXReader对象
        SAXReader reader = new SAXReader();
        try {
            //利用Reader获取Document对象
            Document doc = reader.read(new File(uri));
            //获取根节点并进行递归解析
            parseNode(doc.getRootElement());
            
        } catch (DocumentException e) {
            e.printStackTrace();
        }
    }

    /**
     * 递归解析节点
     * @param node
     */
    private void parseNode(Element node) {
        //System.out.print(node.getName() + ":");
        //获取当前节点属性列表
        List attrlist = node.attributes();
        if (attrlist != null) {
            for (int i = 0; i < attrlist.size(); i++) {
                Attribute attr = attrlist.get(i);
                //System.out.print("[attr]" + attr.getName() + ":" + attr.getValue() + "   ");
            }
        }

        //剔除空白文本
        //输出节点内容
        if(node.getText() != null && !node.getText().trim().equals("")) {
            //System.out.print(node.getText() + "   ");
        }

        //获取所有的子节点进行递归操作
        List eleList = node.elements();
        if (eleList != null) {
            for (Element e : eleList) {
                parseNode(e);
            }
        }
    }
    
    
}

测试代码,简单统计了一下时间: Test.java
package org.devsong.test;

import org.devsong.xmlload.DOM;
import org.devsong.xmlload.Dom4j;
import org.devsong.xmlload.JDOM;
import org.devsong.xmlload.SAX;

public class Test {
    
    public static void main(String[] args) {
        DOM dom = new DOM();
        Dom4j d4j = new Dom4j();
        JDOM jdom = new JDOM();
        SAX sax = new SAX();
        String uri = "src/res/language.xml";
        
        long start = System.currentTimeMillis();
        dom.startParse(uri);
        long end = System.currentTimeMillis();
        System.out.println("DOM: " + (end-start));
        
        start = System.currentTimeMillis();
        sax.startParse(uri);
        end = System.currentTimeMillis();
        System.out.println("SAX: " + (end-start));
        
        start = System.currentTimeMillis();
        jdom.startParse(uri);
        end = System.currentTimeMillis();
        System.out.println("JDOM: " + (end-start));
        
        start = System.currentTimeMillis();
        d4j.startParse(uri);
        end = System.currentTimeMillis();
        System.out.println("DOM4j: " + (end-start));
    }

}
几次测试结果都类似,DOM用时平均下来最长。JDOM和DOM差不多,比DOM好一点点。DOM4j用时比前两者少,速度还行。SAX速度最快,用时大概为DOM的1/4左右。测试的文档为130kb大小的XML。

当然,测试次数较少,测试方法可能不严谨,只是简单测试,对比结果仅供参考。
It's
欢迎访问本站,欢迎留言、分享、点赞。愿您阅读愉快!
*转载请注明出处,严禁非法转载。
https://www.devsong.org
QQ留言 邮箱留言
头像
引用:
取消回复
提交
涂鸦
涂鸦
热门