现在的位置: 首页 > 综合 > 正文

dom4j

2013年02月05日 ⁄ 综合 ⁄ 共 13018字 ⁄ 字号 评论关闭

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用它来读写设备文件

目次

概念
应用简介

  1. 1 读取并解析XML文档
  2. 2 取得Root节点
  3. 3 遍历XML树
  4. 4 XPath支撑
  5. 5 字符串与XML的转换
  6. 6 用XSLT转换XML
  7. 7 创建XML
  8. 8 文件输出
应用介绍2

  1. 1. 下载与安装
  2. 2. 示例XML文档(holen.xml)
  3. 3. 建树一个XML文档
  4. 4. 批改XML文档
  5. 5. 格局化输出和指定编码
  6. 6. 完全的类代码
展开
概念
应用简介

  1. 1 读取并解析XML文档
  2. 2 取得Root节点
  3. 3 遍历XML树
  4. 4 XPath支撑
  5. 5 字符串与XML的转换
  6. 6 用XSLT转换XML
  7. 7 创建XML
  8. 8 文件输出
应用介绍2

  1. 1. 下载与安装
  2. 2. 示例XML文档(holen.xml)
  3. 3. 建树一个XML文档
  4. 4. 批改XML文档
  5. 5. 格局化输出和指定编码
  6. 6. 完全的类代码
展开

 

编辑本段概念

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

 

  Dom4j is an easy to use, open source library for working with XML, XPath and XSLT on the Java platform 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吧。

 

  它的首要接口都在org.dom4j这个包里定义:

 

  Attribute Attribute定义了XML的属性

 

  Branch Branch为可以或许包含子节点的节点如XML元素(Element)和文档(Docuemnts)定义了一个公共的行动,

 

  CDATA CDATA 定义了XML CDATA 区域

 

  CharacterData CharacterData是一个标识接口,标识基于字符的节点。如CDATA,Comment, Text.

 

  Comment Comment 定义了XML注释的行动

 

  Document 定义了XML文档

 

  DocumentType DocumentType 定义XML DOCTYPE声明

 

  Element Element定义XML 元素

 

  ElementHandler ElementHandler定义了 Element 对象的处理惩罚器

 

  ElementPath 被 ElementHandler 应用,用于取合适前正在处理惩罚的路径层次信息

 

  Entity Entity定义 XML entity

 

  Node Node为所有的dom4j中XML节点定义了多态行动

 

  NodeFilter NodeFilter 定义了在dom4j节点中产生的一个滤镜或谓词的行动(predicate)

 

  ProcessingInstruction ProcessingInstruction 定义 XML 处理惩罚指令.

 

  Text Text 定义XML 文本节点.

 

  Visitor Visitor 用于实现Visitor模式.

 

  XPath XPath 在解析一个字符串后会供给一个XPath 表达式

 

  看名字大致就知道它们的涵义如何了。

 

  要想弄懂这套接口,关键的是要熟悉打听接口的持续关系:

 

  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自带的文档),简单说一下如何应用。

1 读取并解析XML文档

  读写XML文档首要依附于org.dom4j.io包,此中供给DOMReader和SAXReader两类不合体式格式,而调用体式格式是一样的。这就是依附接口的益处。

 

  // 从文件读取XML,输入文件名,返回XML文档

 

  public Document read(String fileName) throws MalformedURLException, DocumentException {

 

  SAXReader reader = new SAXReader();

 

  Document document = reader.read(new File(fileName));

 

  return document;

 

  }

 

  此中,reader的read办法是重载的,可以从InputStream, File, Url等多种不合的源来读取。获得的Document对象就代表了全部XML。

 

  按照本人本身的经验,读取的字符编码是遵守XML文件头定义的编码来转换。若是碰到乱码题目,重视要把遍地的编码名称对峙一致即可。

2 取得Root节点

  读取后的第二步,就是获得Root节点。熟悉XML的人都知道,一切XML解析都是从Root元素开端的。

 

  public Element getRootElement(Document doc){

 

  return doc.getRootElement();

 

  }

3 遍历XML树

  DOM4J供给至少3种遍历节点的办法:

 

  1) 列举(Iterator)

 

  // 列举所有子节点

 

  for ( Iterator i = root.elementIterator(); i.hasNext(); ) {

 

  Element element = (Element) i.next();

 

  // do something

 

  }

 

  // 列举名称为foo的节点

 

  for ( Iterator i = root.elementIterator(foo); i.hasNext();) {

 

  Element foo = (Element) i.next();

 

  // do something

 

  }

 

  // 列举属性

 

  for ( Iterator i = root.attributeIterator(); i.hasNext(); ) {

 

  Attribute attribute = (Attribute) i.next();

 

  // do something

 

  }

 

  2)递归

 

  递归也可以采取Iterator作为列举手段,但文档中供给了别的的做法

 

  public void treeWalk() {

 

  treeWalk(getRootElement());

 

  }

 

  public void treeWalk(Element element) {

 

  for (int i = 0, size = element.nodeCount(); i < size; i++) {

 

  Node node = element.node(i);

 

  if (node instanceof Element) {

 

  treeWalk((Element) node);

 

  } else { // do something....

 

  }

 

  }

 

  }

 

  3) Visitor模式

 

  最令人高兴的是DOM4J对Visitor的支撑,如许可以大大缩减代码量,并且清楚易懂。懂得设计模式的人都知道,Visitor是GOF设计模式之一。其首要道理就是两种类互相保有对方的引用,并且一种作为Visitor去接见很多Visitable。我们来看DOM4J中的Visitor模式(快速文档中没有供给)

 

  只须要自定一个类实现Visitor接口即可。

 

  public class MyVisitor extends VisitorSupport {

 

  public void visit(Element element){

 

  System.out.println(element.getName());

 

  }

 

  public void visit(Attribute attr){

 

  System.out.println(attr.getName());

 

  }

 

  }

 

  调用: root.accept(new MyVisitor())

 

  Visitor接口供给多种Visit()的重载,按照XML不合的对象,将采取不合的体式格式来接见。上方是给出的Element和Attribute的简单实现,一般斗劲常用的就是这两个。VisitorSupport是DOM4J供给的默认适配器,Visitor接口的Default Adapter模式,这个模式给出了各类visit(*)的空实现,以便简化代码。

 

  重视,这个Visitor是主动遍历所有子节点的。若是是root.accept(MyVisitor),将遍历子节点。我第一次用的时辰,认为是须要本身遍历,便在递归中调用Visitor,成果可想而知。

4 XPath支撑

  DOM4J对XPath有杰出的支撑,如接见一个节点,可直接用XPath选择。

 

  public void bar(Document document) {

 

  List list = document.Nodes( //foo/bar );

 

  Node node = document.SingleNode(//foo/bar/author);

 

  String name = node.valueOf( @name );

 

  }

 

  例如,若是你想查找XHTML文档中所有的超链接,下面的代码可以实现:

 

  public void findLinks(Document document) throws DocumentException {

 

  List list = document.Nodes( //a/@href );

 

  for (Iterator iter = list.iterator(); iter.hasNext(); ) {

 

  Attribute attribute = (Attribute) iter.next();

 

  String url = attribute.getValue();

 

  }

 

  }

5 字符串与XML的转换

  有时辰经常要用到字符串转换为XML或反之,

 

  // XML转字符串

 

  Document document = ...;

 

  String text = document.asXML();

 

  // 字符串转XML

 

  String text = <name>James</name> </person>;

 

  Document document = DocumentHelper.parseText(text);

6 用XSLT转换XML

  public Document styleDocument(

 

  Document document,

 

  String stylesheet

 

  ) throws Exception {

 

  // load the transformer using JAXP

 

  TransformerFactory factory = TransformerFactory.newInstance();

 

  Transformer transformer = factory.newTransformer(

 

  new StreamSource( stylesheet )

 

  );

 

  // now lets style the given document

 

  DocumentSource source = new DocumentSource( document );

 

  DocumentResult result = new DocumentResult();

 

  transformer.transform( source, result );

 

  // return the transformed document

 

  Document transformedDoc = result.getDocument();

 

  return transformedDoc;

 

  }

7 创建XML

  一般创建XML是写文件前的工作,这就像StringBuffer一样轻易。

 

  public Document createDocument() {

 

  Document document = DocumentHelper.createDocument();

 

  Element root = document.addElement(root);

 

  Element author1 =

 

  root

 

  .addElement(author)

 

  .addAttribute(name, James)

 

  .addAttribute(location, UK)

 

  .addText(James Strachan);

 

  Element author2 =

 

  root

 

  .addElement(author)

 

  .addAttribute(name, Bob)

 

  .addAttribute(location, US)

 

  .addText(Bob McWhirter);

 

  return document;

 

  }

8 文件输出

  一个简单的输出办法是将一个Document或任何的Node经由过程write办法输出

 

  FileWriter out = new FileWriter( foo.xml );

 

  document.write(out);

 

  若是你想改变输出的格局,比如美化输出或缩减格局,可以用XMLWriter类

 

  public void write(Document document) throws IOException {

 

  // 指定文件

 

  XMLWriter writer = new XMLWriter(

 

  new FileWriter( output.xml )

 

  );

 

  writer.write( document );

 

  writer.close();

 

  // 美化格局

 

  OutputFormat format = OutputFormat.createPrettyPrint();

 

  writer = new XMLWriter( System.out, format );

 

  writer.write( document );

 

  // 缩减格局

 

  format = OutputFormat.createCompactFormat();

 

  writer = new XMLWriter( System.out, format );

 

  writer.write( document );

 

  }

 

  如何,DOM4J够简单吧,当然,还有一些错杂的应用没有提到,如ElementHandler等。若是你动心了,那就一路来用DOM4J.

 

编辑本段应用介绍2

  本文首要评论辩论了用dom4j解析XML的根蒂根基题目,包含建树XML文档,添加、批改、删除节点,以合格局化(美化)输出和中文题目。可作为dom4j的入门材料。

1. 下载与安装

  dom4j是sourceforge.net上的一个开源项目,首要用于对XML的解析。从2001年7月公布初版以来,已陆续推出多个版本,今朝最高版本为1.5。

 

  dom4j专门针对Java开辟,应用起来很是简单、直观,在Java界,dom4j正敏捷普及。

 

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

 

  dom4j1.5的完全版大约13M,是一个名为dom4j-1.5.zip的紧缩包,解压后有一个dom4j-1.5.jar文件,这就是应用时须要引入的类包,别的还有一个jaxen-1.1-beta-4.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>

 

  这是一个很简单的XML文档,场景是一个网上书店,有很多书,每本书有两个属性,一个是书名,一个为是否显现[show],最后还有一项是这些书的拥有者[owner]信息。

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内容为Dom4j Tutorials,则删除该节点

 

  /**

 

  * 批改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.Nodes("/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.Nodes("/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.Nodes("/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.Nodes("/books/book/@show" );

 

  list = document.Nodes("/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对象,用于指定显示和编码体式格式。

抱歉!评论已关闭.