Dom4j的使用(Dom4j对xml的解析即增删改查)

Dom4j的使用(Dom4j对xml的解析即增删改查)

      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吧。

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

一、 读取并解析XML文档:



    // 从文件读取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文件头定义的编码来转换。如果遇到乱码问题,注意要把各处的编码名称保持一致即可。
二、取得Root节点
读取后的第二步,就是得到Root节点。熟悉XML的人都知道,一切XML分析都是从Root元素开始的。

    public Element getRootElement(Document doc){
        return doc.getRootElement();
    }

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

1)枚举:


    // 枚举所有子节点
    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)递归





     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模式


         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),将遍历子节点。 

五、 字符串与XML的转换

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

    // XML转字符串
  Document document = ...;
    String text = document.asXML();
// 字符串转XML
    String text =    James   ;
    Document document = DocumentHelper.parseText(text);

六、 用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;
}

七、 创建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;
    }

八、文件输出
    一个简单的输出方法是将一个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 );
    }


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

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"));
    }
}

你可能感兴趣的:(Dom4j的使用(Dom4j对xml的解析即增删改查))