dom4j是一个Java的XML API,类似于jdom,用来读写XML文件的。dom4j是一个非常非常优秀的Java XML API,具有性能优异、功能强大和极端易用使用的特点,同时它也是一个开放源代码的软件,可以在SourceForge上找到它。在IBM developerWorks上面可以找到一篇文章,对主流的Java XML API进行的性能、功能和易用性的评测,dom4j无论在哪个方面都是非常出色的。如今你可以看到越来越多的Java软件都在使用dom4j来读写XML,特别值得一提的是连Sun的JAXM也在用dom4j。这是必须使用的jar包,Hibernate用它来读写配置文件。

 

概念

DOM4J是dom4j.org出品的一个开源XML解析包,它的网站中这样定义:

Dom4j is an easyto use, open source library for working with XML, XPath and XSLT on the Javaplatform using the Java Collections Framework and with full support for DOM,SAX and JAXP.

Dom4j是一个易用的、开源的库,用于XML,XPath和XSLT。它应用于Java平台,采用了Java集合框架并完全支持DOM,SAX和JAXP。

DOM4J使用起来非常简单。只要你了解基本的XML-DOM模型,就能使用。然而他自己带的指南只有短短一页(html),不过说的到健全。国内的中文资料很少。因而俺写这个短小的教程方便大家使用,这篇文章仅谈及基本的用法,如需深入的使用,请……自己摸索或查找别的资料。

之前看过IBM developer社区的文章(参见附录),提到一些XML解析包的性能比较,其中DOM4J的性能非常出色,在多项测试中名列前茅。(事实上DOM4J的官方文档中也引用了这个比较)所以这次的项目中我采用了DOM4J作为XML解析工具。

在国内比较流行的是使用JDOM作为解析器,两者各擅其长,但DOM4J最大的特色是使用大量的接口,这也是它被认为比JDOM灵活的主要原因。大师不是说过么,“面向接口编程”。目前使用DOM4J的已经越来越多。如果你善于使用JDOM,不妨继续用下去,只看看本篇文章作为了解与比较,如果你正要采用一种解析器,不如就用DOM4J吧。

 

下载与安装:

dom4j是sourceforge.net上的一个开源项目,主要用于对XML的解析。从2001年7月发布第一版以来,已陆续推出多个版本,目前最高版本为1.6。

dom4j专门针对Java开发,使用起来非常简单、直观,在Java界,dom4j正迅速普及。

可以到http://sourceforge.net/projects/dom4j下载其最新版。

dom4j1.6的完整版大约13M,是一个名为dom4j-1.6.zip压缩包,解压后有一个dom4j-1.6.jar文件,这就是应用时需要引入的类包,另外还有一个jaxen-1.1-beta-6.jar文件,一般也需要引入,否则执行时可能抛java.lang.NoClassDefFoundError:org/jaxen/JaxenException异常,其他的包可以选择用之。


2示例XML文档(holen.xml

为了述说方便,先看一个XML文档,之后的操作均以此文档为基础。

holen.xml
<?xml version="1.0" encoding="UTF-8"?>
<books>
<!--This is a test for dom4j, holen, 2004.9.11-->
<book show="yes">
<title>Dom4j Tutorials</title>
</book>
<book show="yes">
<title>Lucene Studing</title>
</book>
<book show="no">
<title>Lucene in Action</title>
</book>
<owner>O'Reilly</owner>
</books>

3建立一个XML文档

/**
* 建立一个XML文档,文档名由输入属性决定
* @param filename 需建立的文件名
* @return 返回操作结果, 0表失败, 1表成功
*/
public int createXMLFile(String filename){
/** 返回操作结果, 0表失败, 1表成功 */
    int returnValue = 0;
/** 建立document对象 */
    Document document = DocumentHelper.createDocument();
/** 建立XML文档的根books */
    Element booksElement = document.addElement("books");
/** 加入一行注释 */
    booksElement.addComment("This is a test for dom4j, holen, 2004.9.11");
/** 加入第一个book节点 */ Element bookElement = booksElement.addElement("book");/** 加入show属性内容 */ bookElement.addAttribute("show","yes");/** 加入title节点 */ Element titleElement = bookElement.addElement("title");/** 为title设置内容 */ titleElement.setText("Dom4j Tutorials");/** 类似的完成后两个book */ bookElement = booksElement.addElement("book"); bookElement.addAttribute("show","yes"); titleElement = bookElement.addElement("title"); titleElement.setText("Lucene Studing"); bookElement = booksElement.addElement("book"); bookElement.addAttribute("show","no"); titleElement = bookElement.addElement("title"); titleElement.setText("Lucene in Action");/** 加入owner节点 */ Element ownerElement = booksElement.addElement("owner"); ownerElement.setText("O'Reilly"); try{/** 将document中的内容写入文件中 */ XMLWriter writer = new XMLWriter(new FileWriter(new File(filename))); writer.write(document); writer.close();/** 执行成功,需返回1 */ returnValue = 1; }catch(Exception ex){ ex.printStackTrace();}return returnValue;}



说明:

Document document = DocumentHelper.createDocument();

通过这句定义一个XML文档对象

Element booksElement = document.addElement("books");

通过这句定义一个XML元素,这里添加的是根节点。

Element有几个重要的方法:

l addComment:添加注释

l addAttribute:添加属性

l addElement:添加子元素

最后通过XMLWriter生成物理文件,默认生成的XML文件排版格式比较乱,可以通过OutputFormat类的createCompactFormat()方法或createPrettyPrint()方法格式化输出,默认采用createCompactFormat()方法,显示比较紧凑,这点将在后面详细谈到。

生成后的holen.xml文件内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<books><!--This is a test for dom4j, holen, 2004.9.11-->
<book show="yes"><title>Dom4j Tutorials</title></book>
<book show="yes"><title>Lucene Studing</title></book>
<book show="no"><title>Lucene in Action</title></book>
<owner>O'Reilly</owner>
</books>

4修改XML文档

有三项修改任务,依次为:

l 如果book节点中show属性的内容为yes,则修改成no

l 把owner项内容改为Tshinghua,并添加date节点

l 若title内容为Dom4jTutorials,则删除该节点

/**

* 修改XML文件中内容,并另存为一个新文件

* 重点掌握dom4j中如何添加节点,修改节点,删除节点

* @param filename 修改对象文件
* @param newfilename 修改后另存为该文件
* @return 返回操作结果, 0表失败, 1表成功
*/
public int ModiXMLFile(String filename,String newfilename){
int returnValue = 0;
try{
SAXReader saxReader = new SAXReader();
Document document = saxReader.read(new File(filename));
/** 修改内容之一: 如果book节点中show属性的内容为yes,则修改成no */
/** 先用xpath查找对象 */
List list = document.selectNodes("/books/book/@show" );
Iterator iter = list.iterator();
while(iter.hasNext()){
Attribute attribute = (Attribute)iter.next();
if(attribute.getValue().equals("yes")){
attribute.setValue("no");
}
}
/**
* 修改内容之二: 把owner项内容改为Tshinghua
* 并在owner节点中加入date节点,date节点的内容为2004-09-11,还为date节点添加一个属性type
*/
list = document.selectNodes("/books/owner" );
iter = list.iterator();
if(iter.hasNext()){
Element ownerElement = (Element)iter.next();
ownerElement.setText("Tshinghua");
Element dateElement = ownerElement.addElement("date");
dateElement.setText("2004-09-11");
dateElement.addAttribute("type","Gregorian calendar");
}
/** 修改内容之三: 若title内容为Dom4j Tutorials,则删除该节点 */
list = document.selectNodes("/books/book");
iter = list.iterator();
while(iter.hasNext()){
Element bookElement = (Element)iter.next();
Iterator iterator = bookElement.elementIterator("title");
while(iterator.hasNext()){
Element titleElement=(Element)iterator.next();
if(titleElement.getText().equals("Dom4j Tutorials")){
bookElement.remove(titleElement);
}
}
}
try{
/** 将document中的内容写入文件中 */
XMLWriter writer = new XMLWriter(new FileWriter(new File(newfilename)));
writer.write(document);
writer.close();
/** 执行成功,需返回1 */
returnValue = 1;
}catch(Exception ex){
ex.printStackTrace();
}
}catch(Exception ex){
ex.printStackTrace();
}
return returnValue;
}
说明:
List list = document.selectNodes("/books/book/@show" );
list = document.selectNodes("/books/book");
上述代码通过xpath查找到相应内容。
通过setValue()、setText()修改节点内容。
通过remove()删除节点或属性。

5格式化输出和指定编码

默认的输出方式为紧凑方式,默认编码为UTF-8,但对于我们的应用而言,一般都要用到中文,并且希望显示时按自动缩进的方式的显示,这就需用到OutputFormat类。

/**
* 格式化XML文档,并解决中文问题
* @param filename
* @return
*/
public int formatXMLFile(String filename){
int returnValue = 0;
try{
SAXReader saxReader = new SAXReader();
Document document = saxReader.read(new File(filename));
XMLWriter writer = null;
/** 格式化输出,类型IE浏览一样 */
OutputFormat format = OutputFormat.createPrettyPrint();
/** 指定XML编码 */
format.setEncoding("GBK");
writer= new XMLWriter(new OutputStreamWriter(new FileOutputStream("filename"),format.getEncoding()),format);
writer.write(document);
writer.close();
/** 执行成功,需返回1 */
returnValue = 1;
}catch(Exception ex){
ex.printStackTrace();
}
return returnValue;
}
说明:
OutputFormat format = OutputFormat.createPrettyPrint();
这句指定了格式化的方式为缩进式,则非紧凑式。
format.setEncoding("GBK");
指定编码为GBK。
XMLWriter writer = new XMLWriter(new FileWriter(new File(filename)),format);
这与前面两个方法相比,多加了一个OutputFormat对象,用于指定显示和编码方式。

6完整的类代码

前面提出的方法都是零散的,下面给出完整类代码。

Dom4jDemo.java

package com.holen.dom4j;

import java.io.File;

import java.io.FileWriter;

import java.util.Iterator;

import java.util.List;

import org.dom4j.Attribute;

import org.dom4j.Document;

import org.dom4j.DocumentHelper;

import org.dom4j.Element;

import org.dom4j.io.OutputFormat;

import org.dom4j.io.SAXReader;

importorg.dom4j.io.XMLWriter;


Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐