java中利用Dom4j解析和生成XML文档

一、前言

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

二、准备条件

dom4j.jar

下载地址:http://sourceforge.net/projects/dom4j/

三、使用Dom4j实战

1、解析xml文档

实现思路:

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

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

具体代码如下:

import java.io.File; 
import javaioFileInputStream; 
import javaioInputStream; 
import javautilIterator; 
import javautilList; 
 
import orgdom4jDocument; 
import orgdom4jDocumentHelper; 
import orgdom4jElement; 
import orgdom4jioSAXReader; 
 
/** 
 * 使用dom4j解析xml文档 
 * @author Administrator 
 * 
 */ 
public class Dom4jParseXmlDemo { 
   
  public void parseXml01(){ 
    try{ 
      //将src下面的xml转换为输入流 
      InputStream inputStream = new FileInputStream(new File("D:/project/dynamicWeb/src/resource/modulexml"));  
      //InputStream inputStream = thisgetClass()getResourceAsStream("/modulexml");//也可以根据类的编译文件相对路径去找xml 
      //创建SAXReader读取器,专门用于读取xml 
      SAXReader saxReader = new SAXReader(); 
      //根据saxReader的read重写方法可知,既可以通过inputStream输入流来读取,也可以通过file对象来读取  
      //Document document = saxReaderread(inputStream);  
      Document document = saxReaderread(new File("D:/project/dynamicWeb/src/resource/modulexml"));//必须指定文件的绝对路径 
      //另外还可以使用DocumentHelper提供的xml转换器也是可以的。 
      //Document document = DocumentHelperparseText(" 这个是module标签的文本信息"); 
       
      //获取根节点对象 
      Element rootElement = documentgetRootElement();  
      Systemoutprintln("根节点名称:" + rootElementgetName());//获取节点的名称 
      Systemoutprintln("根节点有多少属性:" + rootElementattributeCount());//获取节点属性数目 
      Systemoutprintln("根节点id属性的值:" + rootElementattributeValue("id"));//获取节点的属性id的值 
      Systemoutprintln("根节点内文本:" + rootElementgetText());//如果元素有子节点则返回空字符串,否则返回节点内的文本 
      //rootElementgetText() 之所以会换行是因为 标签与标签之间使用了tab键和换行符布局,这个也算是文本所以显示出来换行的效果。 
      Systemoutprintln("根节点内文本(1):" + rootElementgetTextTrim());//去掉的是标签与标签之间的tab键和换行符等等,不是内容前后的空格 
      Systemoutprintln("根节点子节点文本内容:" + rootElementgetStringValue()); //返回当前节点递归所有子节点的文本信息。 
       
      //获取子节点 
      Element element = rootElementelement("module"); 
      if(element != null){ 
        Systemoutprintln("子节点的文本:" + elementgetText());//因为子节点和根节点都是Element对象所以它们的操作方式都是相同的 
      } 
      //但是有些情况xml比较复杂,规范不统一,某个节点不存在直接javalangNullPointerException,所以获取到element对象之后要先判断一下是否为空 
       
      rootElementsetName("root");//支持修改节点名称 
      Systemoutprintln("根节点修改之后的名称:" + rootElementgetName()); 
      rootElementsetText("text"); //同样修改标签内的文本也一样 
      Systemoutprintln("根节点修改之后的文本:" + rootElementgetText()); 
    } catch (Exception e) {  
      eprintStackTrace();  
    }  
  } 
   
  public static void main(String[] args) { 
    Dom4jParseXmlDemo demo = new Dom4jParseXmlDemo(); 
    demoparseXml01(); 
  } 
} 

另外上面的xml在src下面,module01.xml具体如下:

 
 
   这个是module标签的文本信息 
 

接下来执行该类的main方法,console效果如下: java中利用Dom4j解析和生成XML文档_第1张图片

由此以知:

<1>dom4j读取xml文件方式有很多样;

<2>取出element对象的文本和标签名称都非常简单;

<3>并且修改元素的文本和标签名称都非常方便,但是不会写入到磁盘xml文件中。

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

具体代码如下:

public void parseXml02(){ 
  try{ 
    //将src下面的xml转换为输入流 
    InputStream inputStream = thisgetClass()getResourceAsStream("/modulexml"); 
    //创建SAXReader读取器,专门用于读取xml 
      SAXReader saxReader = new SAXReader(); 
      //根据saxReader的read重写方法可知,既可以通过inputStream输入流来读取,也可以通过file对象来读取 
      Document document = saxReaderread(inputStream); 
       
      Element rootElement = documentgetRootElement(); 
    Iterator modulesIterator = rootElementelements("module")iterator(); 
    //rootElementelement("name");获取某一个子元素 
    //rootElementelements("name");获取根节点下子元素moudule节点的集合,返回List集合类型 
    //rootElementelements("module")iterator();把返回的list集合里面每一个元素迭代子节点,全部返回到一个Iterator集合中 
    while(modulesIteratorhasNext()){ 
      Element moduleElement = modulesIteratornext(); 
      Element nameElement = moduleElementelement("name"); 
      Systemoutprintln(nameElementgetName() + ":" + nameElementgetText()); 
      Element valueElement = moduleElementelement("value"); 
      Systemoutprintln(valueElementgetName() + ":" + valueElementgetText()); 
      Element descriptElement = moduleElementelement("descript"); 
      Systemoutprintln(descriptElementgetName() + ":" + descriptElementgetText()); 
    }   
  } catch (Exception e) {  
      eprintStackTrace();  
    }  
}  

另外上面的xml在src下面,module02.xml具体如下:

 
 
     
    oa 
    系统基本配置 
    对系统的基本配置根目录 
   
 

接下来执行该类的main方法,console效果如下:java中利用Dom4j解析和生成XML文档_第2张图片

由此以知:

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

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

 
 
   这个是module标签的文本信息 
   
    oa 
    系统基本配置 
    对系统的基本配置根目录 
    这个是子module标签的文本信息 
   
    
    管理配置 
    none 
    管理配置的说明 
     
      系统管理 
      0 
      Config 
       
        部门编号 
        20394 
        编号 
       
     
   
 

因为他们的结构不一样,直接迭代的话 会报错:

java.lang.NullPointerException

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

public void parseXml03(){ 
  try{ 
    //将src下面的xml转换为输入流 
    InputStream inputStream = thisgetClass()getResourceAsStream("/modulexml"); 
    //创建SAXReader读取器,专门用于读取xml 
      SAXReader saxReader = new SAXReader(); 
      //根据saxReader的read重写方法可知,既可以通过inputStream输入流来读取,也可以通过file对象来读取 
      Document document = saxReaderread(inputStream); 
       
      Element rootElement = documentgetRootElement(); 
      if(rootElementelements("module") != null ){ 
      //因为第一个module标签只有内容没有子节点,直接iterator()就javalangNullPointerException了, 所以需要分开实现 
      List elementList = rootElementelements("module"); 
      for (Element element : elementList) { 
        if(!elementgetTextTrim()equals("")){ 
          Systemoutprintln("【1】" + elementgetTextTrim()); 
        }else{ 
          Element nameElement = elementelement("name"); 
          Systemoutprintln("  【2】" + nameElementgetName() + ":" + nameElementgetText()); 
          Element valueElement = elementelement("value"); 
          Systemoutprintln("  【2】" + valueElementgetName() + ":" + valueElementgetText()); 
          Element descriptElement = elementelement("descript"); 
          Systemoutprintln("  【2】" + descriptElementgetName() + ":" + descriptElementgetText()); 
           
          List subElementList = elementelements("module"); 
          for (Element subElement : subElementList) { 
            if(!subElementgetTextTrim()equals("")){ 
              Systemoutprintln("   【3】" + subElementgetTextTrim()); 
            }else{ 
              Element subnameElement = subElementelement("name"); 
              Systemoutprintln("   【3】" + subnameElementgetName() + ":" + subnameElementgetText()); 
              Element subvalueElement = subElementelement("value"); 
              Systemoutprintln("   【3】" + subvalueElementgetName() + ":" + subvalueElementgetText()); 
              Element subdescriptElement = subElementelement("descript"); 
              Systemoutprintln("   【3】" + subdescriptElementgetName() + ":" + subdescriptElementgetText()); 
            } 
          } 
        } 
      } 
      } 
  } catch (Exception e) {  
      eprintStackTrace();  
    }  
} 

接下来执行该类的main方法,console效果如下:java中利用Dom4j解析和生成XML文档_第3张图片

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

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

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

public static void main(String[] args) { 
  String str = " 这个是module标签的文本信息oa系统基本配置对系统的基本配置根目录"; 
  Systemoutprintln(strreplaceAll("<[^<]*>", "_"));  
  Pattern pattern = Patterncompile("<[^<]*>"); 
  Matcher matcher = patternmatcher(str); 
  while(matcherfind()){ 
    str = strreplaceAll(matchergroup(0), matchergroup(0)toUpperCase()); 
  } 
  Systemoutprintln(str); 
    
} 

运行之后效果图如下:java中利用Dom4j解析和生成XML文档_第4张图片

2、生成xml文档

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

实现思路:

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

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

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

具体代码如下:

import java.io.FileWriter; 
import javaioIOException; 
import javaioWriter; 
 
import orgdom4jDocument; 
import orgdom4jDocumentHelper; 
import orgdom4jElement; 
import orgdom4jioXMLWriter; 
 
/** 
 * 使用dom4j生成xml文档 
 * @author Administrator 
 * 
 */ 
public class Dom4jBuildXmlDemo { 
  public void build01(){ 
    try { 
      //DocumentHelper提供了创建Document对象的方法 
      Document document = DocumentHelpercreateDocument(); 
      //添加节点信息 
      Element rootElement = documentaddElement("modules"); 
      //这里可以继续添加子节点,也可以指定内容 
      rootElementsetText("这个是module标签的文本信息"); 
      Element element = rootElementaddElement("module"); 
       
      Element nameElement = elementaddElement("name"); 
      Element valueElement = elementaddElement("value"); 
      Element descriptionElement = elementaddElement("description"); 
      nameElementsetText("名称"); 
      nameElementaddAttribute("language", "java");//为节点添加属性值 
      valueElementsetText("值"); 
      valueElementaddAttribute("language", "c#"); 
      descriptionElementsetText("描述"); 
      descriptionElementaddAttribute("language", "sql server"); 
      Systemoutprintln(documentasXML()); //将document文档对象直接转换成字符串输出 
      Writer fileWriter = new FileWriter("c:\\modulexml"); 
      //dom4j提供了专门写入文件的对象XMLWriter 
      XMLWriter xmlWriter = new XMLWriter(fileWriter); 
      xmlWriterwrite(document); 
      xmlWriterflush(); 
      xmlWriterclose(); 
      Systemoutprintln("xml文档添加成功!"); 
    } catch (IOException e) { 
      eprintStackTrace(); 
    } 
  } 
   
  public static void main(String[] args) { 
    Dom4jBuildXmlDemo demo = new Dom4jBuildXmlDemo(); 
    demobuild01(); 
  } 
} 

运行代码效果如下:java中利用Dom4j解析和生成XML文档_第5张图片
然后去c盘下面查看是否创建成功,结果发现在xml文件中的内容与控制台输出的内容一样。

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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

你可能感兴趣的:(java中利用Dom4j解析和生成XML文档)