【Java编程】Dom4j解析和生成XML文档

 另附

Dom解析和生成xml文档     

http://blog.csdn.net/chenghui0317/article/details/11662667 

一、前言

    dom4j是一套非常优秀的java开源api,主要用于读写xml文档,具有性能优异、功能强大、和非常方便使用的特点。   另外xml经常用于数据交换的载体,像调用webservice传递的参数,以及数据做同步操作等等,   所以使用dom4j解析xml是非常有必要的。

与利用DOM、SAX、JAXP机制来解析xml相比,DOM4J 表现更优秀,具有性能优异、功能强大和极端易用使用的特点,只要懂得DOM基本概念,就可以通过dom4j的api文档来解析xml。dom4j是一套开源的api。实际项目中,往往选择dom4j来作为解析xml的利器。


二、准备条件

   dom4j.jar

下载地址:http://sourceforge.net/projects/dom4j/files/dom4j-2.0.0-ALPHA-2/


三、使用Dom4j实战


先来看看dom4j中对应XML的DOM树建立的继承关系

  

针对于XML标准定义,对应于图2-1列出的内容,dom4j提供了以下实现:

  

同时,dom4j的NodeType枚举实现了XML规范中定义的node类型。如此可以在遍历xml文档的时候通过常量来判断节点类型了。



常用API

 

class org.dom4j.io.SAXReader

 read  提供多种读取xml文件的方式,返回一个Domcument对象

 

interface org.dom4j.Document 

iterator  使用此法获取node
getRootElement  获取根节点


interface org.dom4j.Node

 getName  获取node名字,例如获取根节点名称为bookstore

getNodeType  获取node类型常量值,例如获取到bookstore类型为1——Element
getNodeTypeName  获取node类型名称,例如获取到的bookstore类型名称为Element
 

interface org.dom4j.Element

 attributes  返回该元素的属性列表

attributeValue  根据传入的属性名获取属性值
elementIterator  返回包含子元素的迭代器
elements  返回包含子元素的列表
 

interface org.dom4j.Attribute

getName  获取属性名
getValue  获取属性值
 

interface org.dom4j.Text

 getText  获取Text节点值

 interface org.dom4j.CDATA

 getText  获取CDATA Section值

 interface org.dom4j.Comment

 getText  获取注释 

 


1、解析xml文档

实现思路:

   <1>根据读取的xml路径,传递给SAXReader之后 返回一个Document文档对象;

   <2>然后操作这个Document对象,获取下面的节点以及子节点的信息;

具体代码如下:

  1. 将src下面的xml转换为输入流  
  2.      
  3.     
  4.  //一、根据saxReader的read重写方法可知,既可以通过inputStream输入流来读取,也可以通过file对象来读取  
  5.             SAXReader saxReader = new SAXReader();  
  6.             Document document = saxReader.read(new File("D:/project/dynamicWeb/src/resource/module01.xml"));//必须指定文件的绝对路径  
  7.           
  8.            //  InputStream inputStream = new FileInputStream(new File("D:/project/dynamicWeb/src/resource/module01.xml"));   
  9.            //Document document = saxReader.read(inputStream);
  10.  
  11.          //将src下面的xml转换为输入流  
  12.          //InputStream inputStream = this.getClass().getResourceAsStream("/module01.xml");
  13.            //Document document = saxReader.read(inputStream);
  14.       


  15. //  二 、另外还可以使用DocumentHelper提供的xml转换器也是可以的。
  16.  //String str="<?xml version=\"1.0\" encoding=\"UTF-8\"?><modules id=\"123\"><module> 这               个是module标签的文本信息</module></modules>";//这是xml文档用字符串表示  
  17. //Document document = DocumentHelper.parseText(str);  

上面只是简单的获取了xml的根目录的元素,接下来使用Iterator 迭代器循环document文档对象。

具体代码如下:

[java]  view plain copy print ?
  1. public void parseXml02(){  
  2.     try{  
  3.           //将src下面的xml转换为输入流  
  4.            InputStream inputStream = this.getClass().getResourceAsStream("/module02.xml");  
  5.           //创建SAXReader读取器,专门用于读取xml  
  6.            SAXReader saxReader = new SAXReader();  
  7.            //根据saxReader的read重写方法可知,既可以通过inputStream输入流来读取,也可以通过file对象来读取  
  8.            Document document = saxReader.read(inputStream);  
  9.              
  10.         Element rootElement = document.getRootElement();  //rootElement.getName()值为根  modules标签
  11.         Iterator<Element> modulesIterator = rootElement.elements("module").iterator(); 
  12.  
  13. //DOM4j(Document Object Model For Java)将整个xml文档看做一个对象,每一个标签也是一个对象。通过标签对象就像java对象一样操作函数,对标签操作。
  14.         //rootElement.element("name");获取rootElement下某一个标签为<name>的元素   
  15.         //rootElement.elements("module");获取当前标签子元素标签为<name> </name>节点的集合,返回List集合类型(孙子节点的不算)  
  16.        //rootElement.elements("name");是获取不到的。只是在rootElement子元素中找,找到后放入list集合中,而不会再孙子中找
  17.         //rootElement.elements("module").iterator();返回rootElement标签下所有便签为<module>对象的List<Iterator>,再通过各个对象迭代器取出           对象中子标签。

  18.         while(modulesIterator.hasNext()){  
  19.             Element moduleElement = modulesIterator.next();  
  20.             Element nameElement = moduleElement.element("name");  
  21.             System.out.println(nameElement.getName() + ":" + nameElement.getText());  
  22.             Element valueElement = moduleElement.element("value");  
  23.             System.out.println(valueElement.getName() + ":" + valueElement.getText());  
  24.             Element descriptElement = moduleElement.element("descript");  
  25.             System.out.println(descriptElement.getName() + ":" + descriptElement.getText());  
  26.         }     
  27.     } catch (Exception e) {    
  28.            e.printStackTrace();    
  29.        }    
  30. }     
另外上面的xml在src下面,module02.xml具体如下:
[html]  view plain copy print ?
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <modules id="123">  
  3.     <module>     //使用迭代对有规律数据 
  4.         <name>oa</name>  
  5.         <value>系统基本配置</value>  
  6.         <descript>对系统的基本配置根目录</descript>  
  7.     </module>  

  8. </modules>  
接下来执行该类的main方法,console效果如下:

由此以知: 

   <1>dom4j迭代xml子元素非常的效率和便捷;


但是上面只是简单的迭代了xml的子节点元素,但是如果xml规则比较复杂,比如接下来要测试的module03.xml,具体如下:

[html]  view plain copy print ?
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <modules id="123">  
  3.      <module>这个是module标签的文本信息</module>  <!--1-->
  4.      <module id=" ">  <!--2-->
  5.         <name>oa</name>  
  6.         <value>系统基本配置</value>  
  7.         <descript>对系统的基本配置根目录</descript>  
  8.         <module>这个是子module标签的文本信息</module>  
  9.      </module>  
  10.      <module>  <!--3-->
  11.         <name>管理配置</name>  
  12.         <value>none</value>  
  13.         <descript>管理配置的说明</descript>  
  14.         <module id="106">  
  15.             <name>系统管理</name>  
  16.             <value>0</value>  
  17.             <descript>Config</descript>  
  18.             <module id="107">  
  19.                 <name>部门编号</name>  
  20.                 <value>20394</value>  
  21.                 <descript>编号</descript>  
  22.            </module>  
  23.         </module>  
  24.     </module>  
  25. </modules>  
因为他们的结构不一样(无重复性),直接迭代的话 会报错:

java.lang.NullPointerException

所以这个时候需要小心使用了,每次都不能把元素直接放进去迭代。具体实现代码如下:

[java]  view plain copy print ?
  1. public void parseXml03(){  
  2.     try{  
  3.         //将src下面的xml转换为输入流  
  4.         InputStream inputStream = this.getClass().getResourceAsStream("/module03.xml");  
  5.         //创建SAXReader读取器,专门用于读取xml  
  6.            SAXReader saxReader = new SAXReader();  
  7.            //根据saxReader的read重写方法可知,既可以通过inputStream输入流来读取,也可以通过file对象来读取  
  8.            Document document = saxReader.read(inputStream);  
  9.              
  10.            Element rootElement = document.getRootElement();  
  11.            if(rootElement.elements("module") != null ){  
  12.             //因为第一个module标签只有内容没有子节点,直接.iterator()就java.lang.NullPointerException了, 所以需要分开实现  
  13.             List<Element> elementList = rootElement.elements("module"); //返回rootElement中儿子标签为<module>的个数,只有3个,无孙子中 
  14.             for (Element element : elementList) {  
  15.                 if(!element.getTextTrim().equals("")){  
  16.                     System.out.println("【1】" + element.getTextTrim());  
  17.                 }else{  
  18.                     Element nameElement = element.element("name");  
  19.                     System.out.println("   【2】" + nameElement.getName() + ":" + nameElement.getText());  
  20.                     Element valueElement = element.element("value");  
  21.                     System.out.println("   【2】" + valueElement.getName() + ":" + valueElement.getText());  
  22.                     Element descriptElement = element.element("descript");  
  23.                     System.out.println("   【2】" + descriptElement.getName() + ":" + descriptElement.getText());  
  24.                       
  25.                     List<Element> subElementList = element.elements("module");  
  26.                     for (Element subElement : subElementList) {  
  27.                         if(!subElement.getTextTrim().equals("")){  
  28.                             System.out.println("      【3】" + subElement.getTextTrim());  
  29.                         }else{  
  30.                             Element subnameElement = subElement.element("name");  
  31.                             System.out.println("      【3】" + subnameElement.getName() + ":" + subnameElement.getText());  
  32.                             Element subvalueElement = subElement.element("value");  
  33.                             System.out.println("      【3】" + subvalueElement.getName() + ":" + subvalueElement.getText());  
  34.                             Element subdescriptElement = subElement.element("descript");  
  35.                             System.out.println("      【3】" + subdescriptElement.getName() + ":" + subdescriptElement.getText());  
  36.                         }  
  37.                     }  
  38.                 }  
  39.             }  
  40.            }  
  41.     } catch (Exception e) {    
  42.            e.printStackTrace();    
  43.        }    
  44. }  
接下来执行该类的main方法,console效果如下: (事实上并没有完全输出(部门编号),因为无规律性可言。所以我就改了。这个也是可以解决的)


好了,这下可以解决迭代文档出现空引用的情况了。

另外代码其实可以重构一下,因为循环里面取出子元素的操作都是重复的,可以利用递归改善,但是可读性会变差一点。


如果有些时候需要获取xml中所有的文本信息,又或者别人传递的xml格式不规范,比如标签内名称大小写,虽然xml不区分大小写,但是必须成对出现,所以为了避免这种情况,索性可以将全部的标签名称换为大写,具体代码如下:

[java]  view plain copy print ?
  1. public static void main(String[] args) {  
  2.     String str = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><modules id=\"123\"><module> 这个是module标签的文本信息<name>oa</name><value>系统基本配置</value><descript>对系统的基本配置根目录</descript></module></modules>";  
  3.     System.out.println(str.replaceAll("<[^<]*>""_"));   
  4.     Pattern pattern = Pattern.compile("<[^<]*>");  
  5.     Matcher matcher = pattern.matcher(str);  
  6.     while(matcher.find()){  
  7.         str = str.replaceAll(matcher.group(0), matcher.group(0).toUpperCase());  
  8.     }  
  9.     System.out.println(str);  
  10.        
  11. }  
运行之后效果图如下:



2、生成xml文档

dom4j能够解析xml,同样肯定能生成xml,而且使用起来更加简单方便。

实现思路:

   <1>DocumentHelper提供了创建Document对象的方法;

   <2>操作这个Document对象,添加节点以及节点下的文本、名称和属性值;

   <3>然后利用XMLWriter写入器把封装的document对象写入到磁盘中;

具体代码如下:

[java]  view plain copy print ?
  1. import java.io.FileWriter;  
  2. import java.io.IOException;  
  3. import java.io.Writer;  
  4.   
  5. import org.dom4j.Document;  
  6. import org.dom4j.DocumentHelper;  
  7. import org.dom4j.Element;  
  8. import org.dom4j.io.XMLWriter;  
  9.   
  10. /** 
  11.  * 使用dom4j生成xml文档 
  12.  * @author Administrator 
  13.  * 
  14.  */  
  15. public class Dom4jBuildXmlDemo {  
  16.     public void build01(){  
  17.         try {  
  18.             //DocumentHelper提供了创建Document对象的方法  
  19.             Document document = DocumentHelper.createDocument();  
  20.             //添加节点信息  
  21.             Element rootElement = document.addElement("modules");  
  22.             //这里可以继续添加子节点,也可以指定内容  
  23.             rootElement.setText("这个是module标签的文本信息");  
  24.             Element element = rootElement.addElement("module");  
  25.               
  26.             Element nameElement = element.addElement("name");  
  27.             Element valueElement = element.addElement("value");  
  28.             Element descriptionElement = element.addElement("description");  
  29.             nameElement.setText("名称");  
  30.             nameElement.addAttribute("language""java");//为节点添加属性值  
  31.             valueElement.setText("值");  
  32.             valueElement.addAttribute("language""c#");  
  33.             descriptionElement.setText("描述");  
  34.             descriptionElement.addAttribute("language""sql server");  
  35.             System.out.println(document.asXML()); //将document文档对象直接转换成字符串输出  
  36.             Writer fileWriter = new FileWriter("c:\\module.xml");  
  37.             //dom4j提供了专门写入文件的对象XMLWriter  
  38.             XMLWriter xmlWriter = new XMLWriter(fileWriter);  
  39.             xmlWriter.write(document);  
  40.             xmlWriter.flush();  
  41.             xmlWriter.close();  
  42.             System.out.println("xml文档添加成功!");  
  43.         } catch (IOException e) {  
  44.             e.printStackTrace();  
  45.         }  
  46.     }  
  47.       
  48.     public static void main(String[] args) {  
  49.         Dom4jBuildXmlDemo demo = new Dom4jBuildXmlDemo();  
  50.         demo.build01(); //将方法定义为static就不用new对象了。 
  51.     }  
  52. }  

运行代码效果如下:


然后去c盘下面查看是否创建成功,结果发现在xml文件中的内容与控制台输出的内容一样。

另外上面生成xml并没有指定编码格式,但是还是显示了UTF-8,说明这个是默认的编码格式,如果想重新指定可以在写入到磁盘之前加上document.setXMLEncoding("GBK");就好了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值