情景切入:
最近學校老師佈置一個小作業,要求使用dom4j將xml文件轉換成project.properties配置文件和Excel表格:
如XML文件:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<books type="名著">
<book name="三國演義" author="羅貫中">
<info>三國簡介</info>
</book>
<book name="紅樓夢" author="曹雪芹">
<info>紅樓簡介</info>
</book>
</books>
<books type="小說">
<book name="斗羅大陸" author="唐家三少">
<info>鬥羅簡介</info>
</book>
<book name="誅仙" author="蕭鼎">
<info>誅仙簡介</info>
</book>
</books>
</root>
要求轉換成形如此的配置文件:
此處先就生成此配置文件做一些個人的小結,僅供參考交流學習。
正文:
準備階段:
要想使用dom4j解析xml文件就必須有dom4j的開發環境,由於javaSE中是不含有dom4j的接口的,因此需要手動添加dom4j的jar文件。
考慮受衆可能不知道怎樣使用Eclipse導入jar文件,這裏做一個簡要介紹步驟:
1、創建一個工程
2、建立一個jar文件夾用來存放dom4j.jar文件(如圖)
3、將dom4j.jar文件直接拖拽進jar文件夾(RT)
4、將此java包添加進入工程,步驟如下。
5、當你看到如下圖效果時,恭喜你,你已經可以進行編程了。
好了,環境配好了,可以繼續往下進行了。
要想使用dom4j來解析xml文件,首先要弄懂兩件事(不懂也得知道怎麼用的):
1、xml的結構特點
2、dom4j的api
下面逐一分析:
1、xml的機構特點
以上面的xml文件爲例,其意義上可以看作是是一個樹型結構,總體上是這個樣子
Root有兩個子節點books,每個books又各有兩個子節點book,每個book節點下各有一個子節點info。
而type、name、author等,雖然再文件中也要生成,但他們並不是一個節點,而是這些節點的屬性,而屬性的調用在dom4j中也有相應的方法。
這個結構就暫且說到這,主要是爲了講dom4j的方法好理解一些才涉及的。2、dom4j的API
dom4j的主要接口有:
Attribute |
Attribute定義了XML的屬性 |
Branch |
Branch爲能夠包含子節點的節點如XML元素(Element)和文檔(Docuemnts)定義了一個公共的行爲, |
CDATA |
CDATA定義了XML CDATA 區域 |
CharacterData |
CharacterData是一個標識接口,標識基於字符的節點。如CDATA,Comment, Text. |
Comment |
Comment定義了XML註釋的行爲 |
Document |
Document定義了XML文檔 |
DocumentType |
DocumentType定義XML DOCTYPE聲明 |
Element |
Element定義XML 元素 |
ElementHandler |
ElementHandler定義了 Element 對象的處理器 |
ElementPath |
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表達式 |
實際上,這些接口的命名都是根據他的功能來命名的,看到名字大概也能猜到其作用了吧。
由於dom4j內容很大,而且要完成以上任務根本不需要了解這麼多,感興趣的話可以點擊一下連接,裏面有dom4j的詳細介紹。點擊打開鏈接
我們這裏就只抽其需要的做一下拼接就能完成任務了。
我們需要的就只有Document接口Element接口和Attribute接口,就這三個就足夠了,是不是夠簡單啊?
Document接口:
SAXReader reader = new SAXReader();
Document document = reader.read(newFile(xmlAddress));
- @使用SAXReader創建一個reader對象,通過此對象可以讀取xml文件存在Document的對象中
- @xmlAddress:xml文件的地址,如 "src/demo/books.xml"
Element接口:
Element root=document.getRootElement();
- @通過Document對象的.getRootElement()方法可以獲取根節點<root>
- @此處的root就代表了上面樹圖中的第一個節點。只有通過他,我們才能往下解析,得到更遠節點的屬性名和值。
Element element=root.element("books");
List elemBooksList=root.elements();
由於elements()的返回值爲List<Element>,應該定義一個List數組儲存。- elemBooksList.get(int index) //得到List中第index個元素(index從0開始)
- elemBooksList.size() //得到List的大小
Iterator iterator=root.elementIterator();
通過他得到的是root下所有直接節點的一個迭代器,使用迭代器你就能對這個兩個books節點做遍歷了。- 通過iterator.hasNext();判斷是否迭代器中還有元素,如果有就進入迭代,如果沒有就跳出
- 通過iterator.next();取出此迭代器中的接下來的一個元素
- 要遍歷此樹中的所有節點就要用到數據結構的線序遍歷思想和遞歸方法,這個在接下來的內容中涉及
String elementName=element.getName();
通過getName()方法可以獲得當前節點的節點名,如上圖文件中的[root,books,book,info]這些值。String nodeText=element.getText();
通過getText()方法可以得到當前節點的節點中的內容,如上圖文件中的[三國簡介,紅樓簡介。。。]Attribute attribute=book.attribute("name");
List attList =elem.attributes();
同上2號function。Iterator iterator=book.attributeIterator();
通過他得到的是book節點中所有屬性的一個迭代器,同意你可以迭代遍歷book的幾個屬性[name,author]Attribute接口:
Attribute attribute=book.attribute("name");
- 同Element對象一樣,Attribute對象也有getName()和getText()方法,分別得到屬性的名字和屬性值。
File toPro=new File("src/demo/project1.properties");
BufferedWriter bw=new BufferedWriter(new FileWriter(toPro));
bw.write("要輸出的String"); //...........此處省略若干代碼............
bw.newLine(); //換行
bw.close(); //關閉流
下面來看看代碼實現吧:
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
public class dom4jTest {
public static void main(String[] args) {
String xmlAddress="src/demo/books.xml";
String toProAddess="src/demo/project.properties";
readXML(xmlAddress,toProAddess);
}
static void readXML(String xmlAddress,String toProAddess){
try {
SAXReader reader = new SAXReader();
Document document = reader.read(new File(xmlAddress));
File toPro=new File(toProAddess);
BufferedWriter bw = new BufferedWriter(new FileWriter(toPro));
Element root =document.getRootElement(); //獲取根節點root
String date="【生產時間:"+(new Date()).toString()+"】";
System.out.println(date);
bw.write(date); //寫入日期
bw.newLine();
List elemBooksList=root.elements();
for (int i = 0; i < elemBooksList.size(); i++) {
Element elemBooks=(Element) elemBooksList.get(i);
List attBooksList =elemBooks.attributes();
for (int j = 0; j < attBooksList.size(); j++) {
Attribute att=(Attribute)attBooksList.get(j);
// System.out.println("root.books.["+att.getName()+"]="+att.getText());
bw.write("root.books.["+att.getName()+"]="+att.getText());
bw.newLine();
}
List elemBookList=elemBooks.elements();
for (int m = 0; m < elemBookList.size(); m++) {
Element elemBook=(Element) elemBookList.get(m);
List attBookList =elemBook.attributes();
for (int n = 0; n < attBookList.size(); n++) {
Attribute att=(Attribute)attBookList.get(n);
// System.out.println("root.books.book.["+att.getName()+"]="+att.getText());
bw.write("root.books.book.["+att.getName()+"]="+att.getText());
bw.newLine();
}
Element elemBookInfo=(Element) elemBook.element("info");
// System.out.println("root.books.book."+elemBookInfo.getName()+"="+elemBookInfo.getText());
bw.write("root.books.book."+elemBookInfo.getName()+"="+elemBookInfo.getText());
bw.newLine();
}
}
bw.close();
} catch (DocumentException e) {
System.out.println("xml文件讀取失敗。");
} catch (IOException e) {
System.out.println("IO故障。");
}
}
}