java中利用Dom4j解析和生成XML文档
一、前言
dom4j是一套非常优秀的java开源api,主要用于读写xml文档,具有性能优异、功能强大、和非常方便使用的特点。 另外xml经常用于数据交换的载体,像调用webservice传递的参数,以及数据做同步操作等等, 所以使用dom4j解析xml是非常有必要的。
二、准备条件
dom4j.jar
下载地址:
三、使用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("<?xml version=\"0\" encoding=\"utf-8\"?><modules id=\"123\"><module> 这个是module标签的文本信息</module></modules>"); //获取根节点对象 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具体如下:
<?xml version="0" encoding="utf-8"?> <modules id="123"> <module> 这个是module标签的文本信息</module> </modules>
接下来执行该类的main方法,console效果如下:
由此以知:
<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<element> 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具体如下:
<?xml version="1.0" encoding="utf-8"?> <modules id="123"> <module> <name>oa</name> <value>系统基本配置</value> <descript>对系统的基本配置根目录</descript> </module> </modules>
接下来执行该类的main方法,console效果如下:
由此以知:
<1>dom4j迭代xml子元素非常的效率和便捷;
但是上面只是简单的迭代了xml的子节点元素,但是如果xml规则比较复杂,比如接下来要测试的module03.xml,具体如下:
<?xml version="1.0" encoding="utf-8"?> <modules id="123"> <module>这个是module标签的文本信息</module> <module id=""> <name>oa</name> <value>系统基本配置</value> <descript>对系统的基本配置根目录</descript> <module>这个是子module标签的文本信息</module> </module> <module> <name>管理配置</name> <value>none</value> <descript>管理配置的说明</descript> <module id="106"> <name>系统管理</name> <value>0</value> <descript>config</descript> <module id="107"> <name>部门编号</name> <value>20394</value> <descript>编号</descript> </module> </module> </module> </modules>
因为他们的结构不一样,直接迭代的话 会报错:
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<element> 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<element> 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效果如下:
好了,这下可以解决迭代文档出现空引用的情况了。
另外代码其实可以重构一下,因为循环里面取出子元素的操作都是重复的,可以利用递归改善,但是可读性会变差一点。
如果有些时候需要获取xml中所有的文本信息,又或者别人传递的xml格式不规范,比如标签内名称大小写,虽然xml不区分大小写,但是必须成对出现,所以为了避免这种情况,索性可以将全部的标签名称换为大写,具体代码如下:
public static void main(string[] args) { string str = "<?xml version=\"0\" encoding=\"utf-8\"?><modules id=\"123\"><module> 这个是module标签的文本信息<name>oa</name><value>系统基本配置</value><descript>对系统的基本配置根目录</descript></module></modules>"; systemoutprintln(strreplaceall("<[^<]*>", "_")); pattern pattern = patterncompile("<[^<]*>"); matcher matcher = patternmatcher(str); while(matcherfind()){ str = strreplaceall(matchergroup(0), matchergroup(0)touppercase()); } systemoutprintln(str); }
运行之后效果图如下:
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(); } }
运行代码效果如下:
然后去c盘下面查看是否创建成功,结果发现在xml文件中的内容与控制台输出的内容一样。
另外上面生成xml并没有指定编码格式,但是还是显示了utf-8,说明这个是默认的编码格式,如果想重新指定可以在写入到磁盘之前加上document.setxmlencoding("gbk");就好了。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
推荐阅读
-
java中利用Dom4j解析和生成XML文档
-
java中四种生成和解析XML文档的方法详解(介绍+优缺点比较+示例)
-
java中四种生成和解析XML文档的方法详解(介绍+优缺点比较+示例)
-
java中利用Dom4j解析和生成XML文档
-
java中fastjson生成和解析json数据(序列化和反序列化数据)
-
java中fastjson生成和解析json数据(序列化和反序列化数据)
-
java中fastjson生成和解析json数据(序列化和反序列化数据)
-
Java生成和解析XML格式文件和字符串的实例代码
-
java使用xpath和dom4j解析xml
-
Java生成和解析XML格式文件和字符串的实例代码