一、四种方式的对比
【DOM】
DOM解析是将xml整个读入内存中,并在内存中以DOM树的形式存储。它是与平台无关的官方解析方式,所以不止在Java平台可以用DOM解析,在其他的平台也可以使用。
-优点:
1、树形结构,直观,易于理解,读取方便,代码易编写。
2、树形结构保存在内存中,容易修改。
-缺点
1、因为DOM是将xml文件整个读入内存中,所以对内存消耗大,在xml文件较大时,很容易造成内存溢出的情况。
【SAX】
SAX解析是Java独有的xml文件解析方式,是基于事件驱动的,每当Java程序读到xml文件中的标签头或读到标签结尾时,会触发相应的事件进行业务的处理。
-优点:
1、基于事件驱动,对内存消耗小。
2、适用于只需要处理xml文件中的数据的情况。
-缺点:
1、因为是基于事件驱动的,所以需要针对每一种事件都要编写相应的处理方法,编码比较繁琐。
2、因为SAX并不是一次性把xml读入内存中而是依次读入xml的数据的,所以不能同时操作同一个xml文件中的多个不同的数据。
【JDOM】
DOM和SAX是Java提供的两种基础的解析xml的方式,而JDOM是在基础方法上的扩展,要使用JDOM解析xml文件,需要额外导入jar包。
-优点
1、仅使用具体类而不是用接口。
2、JDOM的API大量使用了Collections类,操作更加方便。
【DOM4J】
DOM4J和JDOM一样,是在Java提供的基础解析xml方式上的扩展,要使用DOM4J也需要导入额外的jar包。
-优点
1、功能强大,能够处理更加复杂的xml文档,包含一些超出基本xml文档的功能。
2、性能优异,对处理较大的xml文件尤为明显。
二、四种方式解析xml文件的性能测试
XmlUtil.java
/**
* 这个类中包含了四种解析XML方式的具体方法
* @author Dan
*
*/
public class XmlUtil {
/**
* DOM解析方式
*/
public void domParseXml() {
System.out.println("=========DOM解析==========");
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
try {
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse("xml/books.xml");
NodeList nodeList = document.getElementsByTagName("book");
for(int i = 0; i < nodeList.getLength(); i++) {
System.out.println("======开始读取书本信息======");
Node node = nodeList.item(i);
NamedNodeMap attrs = node.getAttributes();
for(int j = 0; j < attrs.getLength(); j++) {
Node attr = attrs.item(j);
System.out.println("属性名:" + attr.getNodeName() + "-->属性值:" + attr.getNodeValue());
}
NodeList childList = node.getChildNodes();
for(int k = 0; k < childList.getLength(); k++) {
Node child = childList.item(k);
if(Node.ELEMENT_NODE == child.getNodeType()) {
System.out.println("子节点名:" + child.getNodeName() + "-->子节点值:" + child.getTextContent());
}
}
System.out.println("======读取书本信息结束======");
}
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* SAX解析方式
*/
public void saxParseXml() {
SAXParserFactory factory = SAXParserFactory.newInstance();
try {
SAXParser parser = factory.newSAXParser();
SAXHandler handler = new SAXHandler();
parser.parse("xml/books.xml", handler);
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* JDOM解析方式
*/
public void jdomParseXml() {
System.out.println("==========JDOM解析==========");
SAXBuilder builder = new SAXBuilder();
try {
org.jdom2.Document document = builder.build(new File("xml/books.xml"));
Element root = document.getRootElement();
List<Element> childList = root.getChildren();
for (Element child : childList) {
System.out.println("======开始读取书本信息======");
List<Attribute> attrs = child.getAttributes();
for(Attribute attr : attrs) {
System.out.println("属性名:" + attr.getName() + "-->属性值:" + attr.getValue());
}
List<Element> eleList = child.getChildren();
for(Element element: eleList) {
System.out.println("子节点名:" + element.getName() + "-->子节点值:" + element.getValue());
}
System.out.println("======读取书本信息结束======");
}
} catch (JDOMException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* DOM4J解析方式
*/
@SuppressWarnings("unchecked")
public void dom4JParseXml() {
System.out.println("==========DOM4J解析==========");
SAXReader reader = new SAXReader();
try {
org.dom4j.Document document= reader.read(new File("xml/books.xml"));
org.dom4j.Element root = document.getRootElement();
List<org.dom4j.Element> childList = root.elements();
for(org.dom4j.Element child : childList) {
System.out.println("======开始读取书本信息======");
List<org.dom4j.Attribute> attrs = child.attributes();
for(org.dom4j.Attribute attr : attrs) {
System.out.println("属性名:" + attr.getName() + "-->属性值:" + attr.getValue());
}
List<org.dom4j.Element> eleList = child.elements();
for(org.dom4j.Element element : eleList) {
System.out.println("子节点名:" + element.getName() + "--->子节点值:" + element.getStringValue());
}
System.out.println("======读取书本信息结束======");
}
} catch (DocumentException e) {
e.printStackTrace();
}
}
}SAXHandler.javapublic class SAXHandler extends DefaultHandler {
@Override
public void startDocument() throws SAXException {
super.startDocument();
System.out.println("==========SAX解析==========");
}
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
super.startElement(uri, localName, qName, attributes);
if("book".equals(qName)) {
System.out.println("======开始读取书本信息======");
for(int i = 0; i < attributes.getLength(); i++) {
System.out.println("属性名:" + attributes.getQName(i) + "属性值" + attributes.getValue(i));
}
} else if(!"book".equals(qName) && !"bookstore".equals(qName)) {
System.out.print("子节点" + qName);
}
}
@Override
public void characters(char[] ac, int start, int length) throws SAXException {
super.characters(ac, start, length);
String value = new String(ac, start, length);
if(!"".equals(value.trim())) {
System.out.println("--->节点值:" + value);
}
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
super.endElement(uri, localName, qName);
if("book".equals(qName)) {
System.out.println("======读取书本信息结束======");
}
}
}
TestMain.java
public class TestMain {
public static void main(String[] args) {
XmlUtil util = new XmlUtil();
long domTime, saxTime, jdomTime, dom4JTime, end;
long start = System.currentTimeMillis();
util.domParseXml();
end = System.currentTimeMillis();
domTime = end - start;
start = System.currentTimeMillis();
util.saxParseXml();
end = System.currentTimeMillis();
saxTime = end - start;
start = System.currentTimeMillis();
util.jdomParseXml();
end = System.currentTimeMillis();
jdomTime = end - start;
start = System.currentTimeMillis();
util.dom4JParseXml();
end = System.currentTimeMillis();
dom4JTime = end - start;
System.out.println("DOM:" + domTime);
System.out.println("SAX:" + saxTime);
System.out.println("JDOM:" + jdomTime);
System.out.println("DOM4J:" + dom4JTime);
}
}在xml文件较小时,例如有下面的xml文件:
<?xml version="1.0" encoding="UTF-8"?>
<bookstore>
<book id="1">
<name>冰与火之歌</name>
<author>乔治马丁</author>
<time>2014</time>
<price>89</price>
</book>
<book id="2">
<name>安徒生童话</name>
<price>40</price>
<time>2004</time>
<language>English</language>
</book>
</bookstore>运行结果(省略了输出节点信息内容,直接显示时间信息,结果可能每次都可能不同,仅作参考!):
...一系列输出
DOM:63
SAX:16
JDOM:93
DOM4J:94
可以看到JDOM和DOM4J在文件比较小的时候优势并不明显,SAX解析反而是最快的。
现在使用一个51.5KB的xml文件做实验,运行结果如下(省略了输出节点信息内容,直接显示时间信息,结果可能每次都可能不同,仅作参考!):
...一系列输出
DOM:313
SAX:156
JDOM:187
DOM4J:141
本文对比了Java中四种XML解析方式:DOM、SAX、JDOM和DOM4J。DOM解析将XML文件全部加载到内存,适合小文件但可能导致内存溢出;SAX基于事件驱动,内存消耗小但编码繁琐;JDOM提供更便捷的API,而DOM4J功能强大且性能优异。在小文件中,SAX速度最快,大文件时DOM4J优于JDOM。

782

被折叠的 条评论
为什么被折叠?



