您的位置:首页 > 其它

DOM4J的使用(DOM4J对XML的解析即增删改查)

2014-01-02 22:50 561 查看
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用它来读写配置文件。

在国内比较流行的是使用JDOM作为解析器,两者各擅其长,但DOM4J最大的特色是使用大量的接口,这也是它被认为比JDOM灵活的主要原因。大师不是说过么,“面向接口编程”。目前使用DOM4J的已经越来越多。如果你善于使用JDOM,不妨继续用下去,只看看本篇文章作为了解与比较,如果你正要采用一种解析器,不如就用DOM4J吧。
[align=left]Attribute[/align]
[align=left]Attribute定义了XML的属性[/align]
[align=left]Branch[/align]
[align=left]Branch为能够包含子节点的节点如XML元素(Element)和文档(Docuemnts)定义了一个公共的行为,[/align]
[align=left]CDATA[/align]
[align=left]CDATA 定义了XML CDATA 区域[/align]
[align=left]CharacterData[/align]
[align=left]CharacterData是一个标识借口,标识基于字符的节点。如CDATA,Comment, Text.[/align]
[align=left]Comment[/align]
[align=left]Comment 定义了XML注释的行为[/align]
[align=left]Document[/align]
[align=left]定义了XML文档[/align]
[align=left]DocumentType[/align]
[align=left]DocumentType 定义XML DOCTYPE声明[/align]
[align=left]Element[/align]
[align=left]Element定义XML 元素[/align]
[align=left]ElementHandler[/align]
[align=left]ElementHandler定义了 Element 对象的处理器[/align]
[align=left]ElementPath[/align]
[align=left]被 ElementHandler 使用,用于取得当前正在处理的路径层次信息[/align]
[align=left]Entity[/align]
[align=left]Entity定义 XML entity[/align]
[align=left]Node[/align]
[align=left]Node为所有的dom4j中XML节点定义了多态行为[/align]
[align=left]NodeFilter[/align]
[align=left]NodeFilter 定义了在dom4j节点中产生的一个滤镜或谓词的行为(predicate)[/align]
[align=left]ProcessingInstruction[/align]
[align=left]ProcessingInstruction 定义 XML 处理指令.[/align]
[align=left]Text[/align]
[align=left]Text 定义XML 文本节点.[/align]
[align=left]Visitor[/align]
[align=left]Visitor 用于实现Visitor模式.[/align]
[align=left]XPath[/align]
[align=left]XPath 在分析一个字符串后会提供一个XPath 表达式[/align]
要想弄懂这套接口,关键的是要明白接口的继承关系:

interface java.lang.Cloneable
interface org.dom4j.Node

interface org.dom4j.Attribute
interface org.dom4j.Branch

interface org.dom4j.Document
interface org.dom4j.Element

interface org.dom4j.CharacterData
interface org.dom4j.CDATA

interface org.dom4j.Comment
interface org.dom4j.Text

interface org.dom4j.DocumentType
interface org.dom4j.Entity
interface org.dom4j.ProcessingInstruction

一目了然,很多事情都清楚了。大部分都是由Node继承来的。知道这些关系,将来写程序就不会出现ClassCastException了。

下面给出一些例子(部分摘自DOM4J自带的文档),简单说一下如何使用。

一、 读取并解析XML文档:

[align=left] // 从文件读取XML,输入文件名,返回XML文档[/align]
[align=left] public Document read(String fileName) throws MalformedURLException, DocumentException {[/align]
[align=left] SAXReader reader = new SAXReader();[/align]
[align=left] Document document = reader.read(new File(fileName));[/align]
[align=left] return document;[/align]
[align=left] }[/align]

[align=left]其中,reader的read方法是重载的,可以从InputStream, File, Url等多种不同的源来读取。得到的Document对象就带表了整个XML。[/align]
[align=left]读取的字符编码是按照XML文件头定义的编码来转换。如果遇到乱码问题,注意要把各处的编码名称保持一致即可。[/align]

[align=left]二、取得Root节点[/align]
[align=left]读取后的第二步,就是得到Root节点。熟悉XML的人都知道,一切XML分析都是从Root元素开始的。[/align]

[align=left]  public Element getRootElement(Document doc){[/align]
[align=left] return doc.getRootElement();[/align]
[align=left] }[/align]

三、 遍历XML树(三种方法)

1)枚举:

[align=left] // 枚举所有子节点[/align]
[align=left] for ( Iterator i = root.elementIterator(); i.hasNext(); ) {[/align]
[align=left] Element element = (Element) i.next();[/align]
[align=left] // do something[/align]
[align=left] }[/align]
[align=left] // 枚举名称为foo的节点[/align]
[align=left] for ( Iterator i = root.elementIterator(foo); i.hasNext();) {[/align]
[align=left] Element foo = (Element) i.next();[/align]
[align=left] // do something[/align]
[align=left] }[/align]
[align=left] // 枚举属性[/align]
[align=left] for ( Iterator i = root.attributeIterator(); i.hasNext(); ) {[/align]
[align=left] Attribute attribute = (Attribute) i.next();[/align]
[align=left] // do something[/align]
[align=left] }[/align]
2)递归

[align=left] public void treeWalk() {[/align]
[align=left] treeWalk(getRootElement());[/align]
[align=left] }[/align]
[align=left] public void treeWalk(Element element) {[/align]
[align=left] for (int i = 0, size = element.nodeCount(); i < size; i++) {[/align]
[align=left] Node node = element.node(i);[/align]
[align=left] if (node instanceof Element) {[/align]
[align=left] treeWalk((Element) node);[/align]
[align=left] } else { // do something....[/align]
[align=left] }[/align]
[align=left] }[/align]
[align=left]}[/align]

3)Visitor模式

[align=left]  public class MyVisitor extends VisitorSupport {[/align]
[align=left] public void visit(Element element){[/align]
[align=left] System.out.println(element.getName());[/align]
[align=left] }[/align]
[align=left] public void visit(Attribute attr){[/align]
[align=left] System.out.println(attr.getName());[/align]
[align=left] }[/align]
[align=left] }[/align]

[align=left] 调用: root.accept(new MyVisitor())[/align]
[align=left] Visitor接口提供多种Visit()的重载,根据XML不同的对象,将采用不同的方式来访问。上面是给出的Element和Attribute的简单实现,一般比较常用的就是这两个。VisitorSupport是DOM4J提供的默认适配器,Visitor接口的Default Adapter模式,这个模式给出了各种visit(*)的空实现,以便简化代码。[/align]

注意,这个Visitor是自动遍历所有子节点的。如果是root.accept(MyVisitor),将遍历子节点。

五、 字符串与XML的转换

[align=left]有时候经常要用到字符串转换为XML或反之,[/align]
[align=left] // XML转字符串[/align]
[align=left]  Document document = ...;[/align]
[align=left] String text = document.asXML();[/align]
[align=left]// 字符串转XML[/align]
[align=left] String text = James ;[/align]
[align=left] Document document = DocumentHelper.parseText(text);[/align]

[align=left]六、 用XSLT转换XML[/align]
[align=left] public Document styleDocument([/align]
[align=left] Document document,[/align]
[align=left] String stylesheet[/align]
[align=left] ) throws Exception {[/align]
[align=left] // load the transformer using JAXP[/align]
[align=left] TransformerFactory factory = TransformerFactory.newInstance();[/align]
[align=left] Transformer transformer = factory.newTransformer([/align]
[align=left] new StreamSource( stylesheet )[/align]
[align=left] );[/align]
[align=left] // now lets style the given document[/align]
[align=left] DocumentSource source = new DocumentSource( document );[/align]
[align=left] DocumentResult result = new DocumentResult();[/align]
[align=left] transformer.transform( source, result );[/align]
[align=left] // return the transformed document[/align]
[align=left] Document transformedDoc = result.getDocument();[/align]
[align=left] return transformedDoc;[/align]
[align=left]}[/align]

[align=left]七、 创建XML[/align]
[align=left] 一般创建XML是写文件前的工作,这就像StringBuffer一样容易。[/align]
[align=left] public Document createDocument() {[/align]
[align=left] Document document = DocumentHelper.createDocument();[/align]
[align=left] Element root = document.addElement(root);[/align]
[align=left] Element author1 =[/align]
[align=left] root[/align]
[align=left] .addElement(author)[/align]
[align=left] .addAttribute(name, James)[/align]
[align=left] .addAttribute(location, UK)[/align]
[align=left] .addText(James Strachan);[/align]
[align=left] Element author2 =[/align]
[align=left] root[/align]
[align=left] .addElement(author)[/align]
[align=left] .addAttribute(name, Bob)[/align]
[align=left] .addAttribute(location, US)[/align]
[align=left] .addText(Bob McWhirter);[/align]
[align=left] return document;[/align]
[align=left] }[/align]

[align=left]八、文件输出[/align]
[align=left] 一个简单的输出方法是将一个Document或任何的Node通过write方法输出[/align]
[align=left] FileWriter out = new FileWriter( foo.xml );[/align]
[align=left] document.write(out);[/align]

[align=left] 如果你想改变输出的格式,比如美化输出或缩减格式,可以用XMLWriter类[/align]
[align=left] public void write(Document document) throws IOException {[/align]
[align=left] // 指定文件[/align]
[align=left] XMLWriter writer = new XMLWriter([/align]
[align=left] new FileWriter( output.xml )[/align]
[align=left] );[/align]
[align=left] writer.write( document );[/align]
[align=left] writer.close();[/align]
[align=left] // 美化格式[/align]
[align=left] OutputFormat format = OutputFormat.createPrettyPrint();[/align]
[align=left] writer = new XMLWriter( System.out, format );[/align]
[align=left] writer.write( document );[/align]
[align=left] // 缩减格式[/align]
[align=left] format = OutputFormat.createCompactFormat();[/align]
[align=left] writer = new XMLWriter( System.out, format );[/align]
[align=left] writer.write( document );[/align]
[align=left] }[/align]

最后附上,我做测试一份简单代码:

package com.test;

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;

import org.dom4j.io.XMLWriter;

public class XMLTest {

/**

* 建立一个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");

/** 格式化输出,类型IE浏览一样 */

OutputFormat format = OutputFormat.createPrettyPrint();

/** 指定XML编码 */

format.setEncoding("GBK");

try{

/** 将document中的内容写入文件中 */

XMLWriter writer = new XMLWriter(new FileWriter(new File(filename)),format);

writer.write(document);

writer.close();

/** 执行成功,需返回1 */

returnValue = 1;

}catch(Exception ex){

ex.printStackTrace();

}

return returnValue;

}

/**

* 修改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;

}

/**

* 格式化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("UTF-8");

writer= new XMLWriter(new FileWriter(new File(filename)),format);

writer.write(document);

writer.close();

/** 执行成功,需返回1 */

returnValue = 1;

}catch(Exception ex){

ex.printStackTrace();

}

return returnValue;

}

public static void main(String[] args) {

XMLTest xmlTest= new XMLTest();

System.out.println(xmlTest.createXMLFile("holen.xml"));

// System.out.println(xmlTest.ModiXMLFile("holen.xml", "newholen.xml"));

// System.out.println(xmlTest.formatXMLFile("holen.xml"));

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: