java中利用Dom4j解析和生成XML文檔
一、前言
dom4j是一套非常優(yōu)秀的Java開源api,主要用于讀寫xml文檔,具有性能優(yōu)異、功能強(qiáng)大、和非常方便使用的特點(diǎn)。 另外xml經(jīng)常用于數(shù)據(jù)交換的載體,像調(diào)用webservice傳遞的參數(shù),以及數(shù)據(jù)做同步操作等等, 所以使用dom4j解析xml是非常有必要的。
二、準(zhǔn)備條件
dom4j.jar
下載地址:http://sourceforge.net/projects/dom4j/
三、使用Dom4j實(shí)戰(zhàn)
1、解析xml文檔
實(shí)現(xiàn)思路:
<1>根據(jù)讀取的xml路徑,傳遞給SAXReader之后 返回一個(gè)Document文檔對象;
<2>然后操作這個(gè)Document對象,獲取下面的節(jié)點(diǎn)以及子節(jié)點(diǎn)的信息;
具體代碼如下:
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轉(zhuǎn)換為輸入流 InputStream inputStream = new FileInputStream(new File("D:/project/dynamicWeb/src/resource/modulexml")); //InputStream inputStream = thisgetClass()getResourceAsStream("/modulexml");//也可以根據(jù)類的編譯文件相對路徑去找xml //創(chuàng)建SAXReader讀取器,專門用于讀取xml SAXReader saxReader = new SAXReader(); //根據(jù)saxReader的read重寫方法可知,既可以通過inputStream輸入流來讀取,也可以通過file對象來讀取 //Document document = saxReaderread(inputStream); Document document = saxReaderread(new File("D:/project/dynamicWeb/src/resource/modulexml"));//必須指定文件的絕對路徑 //另外還可以使用DocumentHelper提供的xml轉(zhuǎn)換器也是可以的。 //Document document = DocumentHelperparseText("<?xml version=\"0\" encoding=\"UTF-8\"?><modules id=\"123\"><module> 這個(gè)是module標(biāo)簽的文本信息</module></modules>"); //獲取根節(jié)點(diǎn)對象 Element rootElement = documentgetRootElement(); Systemoutprintln("根節(jié)點(diǎn)名稱:" + rootElementgetName());//獲取節(jié)點(diǎn)的名稱 Systemoutprintln("根節(jié)點(diǎn)有多少屬性:" + rootElementattributeCount());//獲取節(jié)點(diǎn)屬性數(shù)目 Systemoutprintln("根節(jié)點(diǎn)id屬性的值:" + rootElementattributeValue("id"));//獲取節(jié)點(diǎn)的屬性id的值 Systemoutprintln("根節(jié)點(diǎn)內(nèi)文本:" + rootElementgetText());//如果元素有子節(jié)點(diǎn)則返回空字符串,否則返回節(jié)點(diǎn)內(nèi)的文本 //rootElementgetText() 之所以會換行是因?yàn)?標(biāo)簽與標(biāo)簽之間使用了tab鍵和換行符布局,這個(gè)也算是文本所以顯示出來換行的效果。 Systemoutprintln("根節(jié)點(diǎn)內(nèi)文本(1):" + rootElementgetTextTrim());//去掉的是標(biāo)簽與標(biāo)簽之間的tab鍵和換行符等等,不是內(nèi)容前后的空格 Systemoutprintln("根節(jié)點(diǎn)子節(jié)點(diǎn)文本內(nèi)容:" + rootElementgetStringValue()); //返回當(dāng)前節(jié)點(diǎn)遞歸所有子節(jié)點(diǎn)的文本信息。 //獲取子節(jié)點(diǎn) Element element = rootElementelement("module"); if(element != null){ Systemoutprintln("子節(jié)點(diǎn)的文本:" + elementgetText());//因?yàn)樽庸?jié)點(diǎn)和根節(jié)點(diǎn)都是Element對象所以它們的操作方式都是相同的 } //但是有些情況xml比較復(fù)雜,規(guī)范不統(tǒng)一,某個(gè)節(jié)點(diǎn)不存在直接javalangNullPointerException,所以獲取到element對象之后要先判斷一下是否為空 rootElementsetName("root");//支持修改節(jié)點(diǎn)名稱 Systemoutprintln("根節(jié)點(diǎn)修改之后的名稱:" + rootElementgetName()); rootElementsetText("text"); //同樣修改標(biāo)簽內(nèi)的文本也一樣 Systemoutprintln("根節(jié)點(diǎn)修改之后的文本:" + 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> 這個(gè)是module標(biāo)簽的文本信息</module> </modules>
接下來執(zhí)行該類的main方法,console效果如下:
由此以知:
<1>dom4j讀取xml文件方式有很多樣;
<2>取出element對象的文本和標(biāo)簽名稱都非常簡單;
<3>并且修改元素的文本和標(biāo)簽名稱都非常方便,但是不會寫入到磁盤xml文件中。
上面只是簡單的獲取了xml的根目錄的元素,接下來使用Iterator 迭代器循環(huán)document文檔對象。
具體代碼如下:
public void parseXml02(){ try{ //將src下面的xml轉(zhuǎn)換為輸入流 InputStream inputStream = thisgetClass()getResourceAsStream("/modulexml"); //創(chuàng)建SAXReader讀取器,專門用于讀取xml SAXReader saxReader = new SAXReader(); //根據(jù)saxReader的read重寫方法可知,既可以通過inputStream輸入流來讀取,也可以通過file對象來讀取 Document document = saxReaderread(inputStream); Element rootElement = documentgetRootElement(); Iterator<Element> modulesIterator = rootElementelements("module")iterator(); //rootElementelement("name");獲取某一個(gè)子元素 //rootElementelements("name");獲取根節(jié)點(diǎn)下子元素moudule節(jié)點(diǎn)的集合,返回List集合類型 //rootElementelements("module")iterator();把返回的list集合里面每一個(gè)元素迭代子節(jié)點(diǎn),全部返回到一個(gè)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>系統(tǒng)基本配置</value> <descript>對系統(tǒng)的基本配置根目錄</descript> </module> </modules>
接下來執(zhí)行該類的main方法,console效果如下:
由此以知:
<1>dom4j迭代xml子元素非常的效率和便捷;
但是上面只是簡單的迭代了xml的子節(jié)點(diǎn)元素,但是如果xml規(guī)則比較復(fù)雜,比如接下來要測試的module03.xml,具體如下:
<?xml version="1.0" encoding="UTF-8"?> <modules id="123"> <module>這個(gè)是module標(biāo)簽的文本信息</module> <module id=""> <name>oa</name> <value>系統(tǒng)基本配置</value> <descript>對系統(tǒng)的基本配置根目錄</descript> <module>這個(gè)是子module標(biāo)簽的文本信息</module> </module> <module> <name>管理配置</name> <value>none</value> <descript>管理配置的說明</descript> <module id="106"> <name>系統(tǒng)管理</name> <value>0</value> <descript>Config</descript> <module id="107"> <name>部門編號</name> <value>20394</value> <descript>編號</descript> </module> </module> </module> </modules>
因?yàn)樗麄兊慕Y(jié)構(gòu)不一樣,直接迭代的話 會報(bào)錯(cuò):
java.lang.NullPointerException
所以這個(gè)時(shí)候需要小心使用了,每次都不能把元素直接放進(jìn)去迭代。具體實(shí)現(xiàn)代碼如下:
public void parseXml03(){ try{ //將src下面的xml轉(zhuǎn)換為輸入流 InputStream inputStream = thisgetClass()getResourceAsStream("/modulexml"); //創(chuàng)建SAXReader讀取器,專門用于讀取xml SAXReader saxReader = new SAXReader(); //根據(jù)saxReader的read重寫方法可知,既可以通過inputStream輸入流來讀取,也可以通過file對象來讀取 Document document = saxReaderread(inputStream); Element rootElement = documentgetRootElement(); if(rootElementelements("module") != null ){ //因?yàn)榈谝粋€(gè)module標(biāo)簽只有內(nèi)容沒有子節(jié)點(diǎn),直接iterator()就javalangNullPointerException了, 所以需要分開實(shí)現(xiàn) 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(); } }
接下來執(zhí)行該類的main方法,console效果如下:
好了,這下可以解決迭代文檔出現(xiàn)空引用的情況了。
另外代碼其實(shí)可以重構(gòu)一下,因?yàn)檠h(huán)里面取出子元素的操作都是重復(fù)的,可以利用遞歸改善,但是可讀性會變差一點(diǎn)。
如果有些時(shí)候需要獲取xml中所有的文本信息,又或者別人傳遞的xml格式不規(guī)范,比如標(biāo)簽內(nèi)名稱大小寫,雖然xml不區(qū)分大小寫,但是必須成對出現(xiàn),所以為了避免這種情況,索性可以將全部的標(biāo)簽名稱換為大寫,具體代碼如下:
public static void main(String[] args) { String str = "<?xml version=\"0\" encoding=\"UTF-8\"?><modules id=\"123\"><module> 這個(gè)是module標(biāo)簽的文本信息<name>oa</name><value>系統(tǒng)基本配置</value><descript>對系統(tǒng)的基本配置根目錄</descript></module></modules>"; Systemoutprintln(strreplaceAll("<[^<]*>", "_")); Pattern pattern = Patterncompile("<[^<]*>"); Matcher matcher = patternmatcher(str); while(matcherfind()){ str = strreplaceAll(matchergroup(0), matchergroup(0)toUpperCase()); } Systemoutprintln(str); }
運(yùn)行之后效果圖如下:
2、生成xml文檔
dom4j能夠解析xml,同樣肯定能生成xml,而且使用起來更加簡單方便。
實(shí)現(xiàn)思路:
<1>DocumentHelper提供了創(chuàng)建Document對象的方法;
<2>操作這個(gè)Document對象,添加節(jié)點(diǎn)以及節(jié)點(diǎn)下的文本、名稱和屬性值;
<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提供了創(chuàng)建Document對象的方法 Document document = DocumentHelpercreateDocument(); //添加節(jié)點(diǎn)信息 Element rootElement = documentaddElement("modules"); //這里可以繼續(xù)添加子節(jié)點(diǎn),也可以指定內(nèi)容 rootElementsetText("這個(gè)是module標(biāo)簽的文本信息"); Element element = rootElementaddElement("module"); Element nameElement = elementaddElement("name"); Element valueElement = elementaddElement("value"); Element descriptionElement = elementaddElement("description"); nameElementsetText("名稱"); nameElementaddAttribute("language", "java");//為節(jié)點(diǎn)添加屬性值 valueElementsetText("值"); valueElementaddAttribute("language", "c#"); descriptionElementsetText("描述"); descriptionElementaddAttribute("language", "sql server"); Systemoutprintln(documentasXML()); //將document文檔對象直接轉(zhuǎn)換成字符串輸出 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(); } }
運(yùn)行代碼效果如下:
然后去c盤下面查看是否創(chuàng)建成功,結(jié)果發(fā)現(xiàn)在xml文件中的內(nèi)容與控制臺輸出的內(nèi)容一樣。
另外上面生成xml并沒有指定編碼格式,但是還是顯示了UTF-8,說明這個(gè)是默認(rèn)的編碼格式,如果想重新指定可以在寫入到磁盤之前加上document.setXMLEncoding("GBK");就好了。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
java使用枚舉封裝錯(cuò)誤碼及錯(cuò)誤信息詳解
這篇文章主要介紹了java使用枚舉封裝錯(cuò)誤碼及錯(cuò)誤信息,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12Java使用自定義注解+反射實(shí)現(xiàn)字典轉(zhuǎn)換代碼實(shí)例
這篇文章主要介紹了Java使用自定義注解+反射實(shí)現(xiàn)字典轉(zhuǎn)換代碼實(shí)例,注解是一種能被添加到j(luò)ava代碼中的元數(shù)據(jù),類、方法、變量、參數(shù)和包都可以用注解來修飾,注解對于它所修飾的代碼并沒有直接的影響,需要的朋友可以參考下2023-09-09詳解Intellij IDEA 2017 debug斷點(diǎn)調(diào)試技巧(總結(jié))
這篇文章主要介紹了詳解Intellij IDEA 2017 debug斷點(diǎn)調(diào)試技巧(總結(jié)),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-11-11Java Servlet線程中AsyncContext異步處理Http請求
這篇文章主要介紹了Java Servlet線程中AsyncContext異步處理Http請求及在業(yè)務(wù)中應(yīng)用,AsyncContext是Servlet 3.0使Servlet 線程不再需要一直阻塞,直到業(yè)務(wù)處理完畢才能再輸出響應(yīng),最后才結(jié)束該Servlet線程2023-03-03Java使用dom4j實(shí)現(xiàn)對xml簡單的增刪改查操作示例
這篇文章主要介紹了Java使用dom4j實(shí)現(xiàn)對xml簡單的增刪改查操作,結(jié)合實(shí)例形式詳細(xì)分析了Java使用dom4j實(shí)現(xiàn)對xml簡單的增刪改查基本操作技巧與相關(guān)注意事項(xiàng),需要的朋友可以參考下2020-05-05基于IOC容器實(shí)現(xiàn)管理mybatis過程解析
這篇文章主要介紹了基于IOC容器實(shí)現(xiàn)管理mybatis過程解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-07-07