使用步驟:
1)導入dom4j的核心包。 dom4j-1.6.1.jar(點擊下載)
2)編寫Dom4j讀取xml文件代碼
相關方法
節點:
Iterator Element.nodeIterator(); //獲取當前標籤節點下的所有子節點
標籤:
Element Document.getRootElement(); //獲取xml文檔的根標籤
Element ELement.element("標籤名") //指定名稱的第一個子標籤
Iterator<Element> Element.elementIterator("標籤名");// 指定名稱的所有子標籤
List<Element> Element.elements(); //獲取所有子標籤
屬性:
String Element.attributeValue("屬性名") //獲取指定名稱的屬性值
Attribute Element.attribute("屬性名");//獲取指定名稱的屬性對象
Attribute.getName() //獲取屬性名稱
Attibute.getValue() //獲取屬性值
List<Attribute> Element.attributes(); //獲取所有屬性對象
Iterator<Attribute> Element.attibuteIterator(); //獲取所有屬性對象
文本:
Element.getText(); //獲取當前標籤的文本
Element.elementText("標籤名") //獲取當前標籤的指定名稱的子標籤的文本內容
(1)寫出內容到xml文檔
XMLWriter writer = new XMLWriter(OutputStream, OutputForamt)
wirter.write(Document);
(2)常用方法
增加
Ø DocumentHelper.createDocument(); 增加文檔
Ø addElement(名稱) 增加標籤
Ø addAttribute(名稱,值) 增加屬性
修改
Ø Attribute.setValue(值)
Ø Element.addAttribute(屬性名,值)
Ø Element.setText(內容)
刪除
Ø Element.detach()
Ø Attribute.detach()
核心的API:
SAXParser類: 用於讀取和解析xml文件對象
parse(File f,
DefaultHandler dh
)方法: 參數一: File:表示 讀取的xml文件。
參數二: DefaultHandler: SAX事件處理程序。使用DefaultHandler的子類[一個類繼承class 類名(extends DefaultHandler) 在調用是創建傳進去
例如:
1
2
3
4
5
6
|
//創建SAXParser對象
SAXParser parser=SAXParserFactory.newInstance().newSAXParser();
//調用parse方法
parser.parse(
new
File(
"./src/contact.xml"
),
new
MyDefaultHandler());
|
DefaultHandler類的API:
void startDocument() : 在讀到文檔開始時調用
void endDocument() :在讀到文檔結束時調用
void startElement(String uri, String localName, String qName, Attributes attributes) :讀到開始標籤時調用
void endElement(String uri, String localName, String qName) :讀到結束標籤時調用
void characters(char[] ch, int start, int length) : 讀到文本內容時調用
DOM解析 |
SAX解析 |
原理: 一次性加載xml文檔,不適合大容量的文件讀取 |
原理: 加載一點,讀取一點,處理一點。適合大容量文件的讀取 |
DOM解析可以任意進行增刪改成 |
SAX解析只能讀取 |
DOM解析任意讀取任何位置的數據,甚至往回讀 |
SAX解析只能從上往下,按順序讀取,不能往回讀 |
DOM解析面向對象的編程方法(Node,Element,Attribute),Java開發者編碼比較簡單。 |
SAX解析基於事件的編程方法。java開發編碼相對複雜。 |
(1)xPath的作用: 主要是用於快速獲取所需的節點對象 ( 在dom4j中如何使用xPath技術)
(2)步驟及方法
導入xPath支持jar包 。 jaxen-1.1-beta-6.jar(點擊下載)
使用xpath方法
List<Node> selectNodes("xpath表達式"); 查詢多個節點對象
Node selectSingleNode("xpath表達式"); 查詢一個節點對象
(3)xPath語法
/ 絕對路徑 表示從xml的根位置開始或子元素(一個層次結構)
// 相對路徑 表示不分任何層次結構的選擇元素。
* 通配符 表示匹配所有元素
[] 條件 表示選擇什麼條件下的元素
@ 屬性 表示選擇屬性節點 //BBB[@name='bbb'] 選擇含有屬性name且其值爲'bbb'的BBB元素
and 關係 表示條件的與關係(等價於&&)
text() 文本 表示選擇文本內容
創建一個通訊錄,有聯繫人的各種信息,在控制檯有一些功能,及具體實現效果如圖
對應生成的xml文件
首先,分解下一下,既然是一個聯繫人,有衆多屬性,我們可以考略通過創建一個Contact類同時將其封裝,如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
|
package
com.gqx.Test;
public
class
Contact {
private
String Id;
private
String name;
private
String sex;
private
String age;
private
String phone;
private
String qq;
private
String email;
public
String getId() {
return
Id;
}
public
void
setId(String id) {
Id = id;
}
public
String getName() {
return
name;
}
public
void
setName(String name) {
this
.name = name;
}
public
String getSex() {
return
sex;
}
public
void
setSex(String sex) {
this
.sex = sex;
}
public
String getAge() {
return
age;
}
public
void
setAge(String age) {
this
.age = age;
}
public
String getPhone() {
return
phone;
}
public
void
setPhone(String phone) {
this
.phone = phone;
}
public
String getQq() {
return
qq;
}
public
void
setQq(String qq) {
this
.qq = qq;
}
public
String getEmail() {
return
email;
}
public
void
setEmail(String email) {
this
.email = email;
}
@Override
public
String toString() {
return
"Contact [Id="
+ Id +
", name="
+ name +
", sex="
+ sex
+
", age="
+ age +
", phone="
+ phone +
", qq="
+ qq
+
", email="
+ email +
"]"
;
}
}
|
其次考略到改程序額主菜單這些目錄實現的操作比較複雜,不能一起堆放在主程序中,這時可以考慮創建一個抽象的接口將目錄功能做一個彙總,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
package
com.gqx.Test;
import
java.io.FileNotFoundException;
import
java.io.UnsupportedEncodingException;
import
java.util.List;
import
org.dom4j.DocumentException;
public
interface
ContactOperate {
public
void
addContact(Contact contact)
throws
Exception;
public
void
ModifyContact(Contact contact)
throws
Exception;
public
void
removeContact(String id)
throws
Exception;
public
List<Contact> checkContacts();
}
|
這個時候我們就可以寫出主程序了,雖然上面接口的具體方法,我們還沒有實現,我們先把框架搭好
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
|
package
com.gqx.Test;
import
java.io.BufferedReader;
import
java.io.IOException;
import
java.io.InputStreamReader;
import
java.util.List;
import
java.util.Scanner;
public
class
Menu {
public
static
void
main(String[] args)
throws
Exception {
// TODO Auto-generated method stub
Scanner bf=
new
Scanner(System.in);
//創建接口,同時對實例化它的實現接口
ContactOperate operator=
new
Operator();
while
(
true
) {
//看到菜單
printMenu();
//讀取用戶輸入
int
command=Integer.parseInt(bf.nextLine());
switch
(command) {
case
1
:
//1、添加聯繫人
Contact contact=
new
Contact();
System.out.println(
"請輸入聯繫人姓名:"
);
String name=bf.nextLine();
contact.setName(name);
System.out.println(
"請輸入聯繫人ID:"
);
String id=bf.nextLine();
contact.setId(id);
System.out.println(
"請輸入聯繫人性別:"
);
String sex=bf.nextLine();
contact.setSex(sex);
System.out.println(
"請輸入聯繫人年齡:"
);
String age=bf.nextLine();
contact.setAge(age);
System.out.println(
"請輸入聯繫人電話:"
);
String phone=bf.nextLine();
contact.setPhone(phone);
System.out.println(
"請輸入聯繫人郵箱:"
);
String email=bf.nextLine();
contact.setEmail(email);
System.out.println(
"請輸入聯繫人qq:"
);
String qq=bf.nextLine();
contact.setQq(qq);
System.out.println(contact);
operator.addContact(contact);
break
;
case
2
:
Contact contact1=
new
Contact();
System.out.println(
"請輸入要修改的聯繫人ID:"
);
String id1=bf.nextLine();
contact1.setId(id1);
System.out.println(
"請輸入修改聯繫人姓名:"
);
String name1=bf.nextLine();
contact1.setName(name1);
System.out.println(
"請輸入修改聯繫人性別:"
);
String sex1=bf.nextLine();
contact1.setSex(sex1);
System.out.println(
"請輸入修改聯繫人年齡:"
);
String age1=bf.nextLine();
contact1.setAge(age1);
System.out.println(
"請輸入修改聯繫人電話:"
);
String phone1=bf.nextLine();
contact1.setPhone(phone1);
System.out.println(
"請輸入修改聯繫人郵箱:"
);
String email1=bf.nextLine();
contact1.setEmail(email1);
System.out.println(
"請輸入修改聯繫人qq:"
);
String qq1=bf.nextLine();
contact1.setQq(qq1);
operator.ModifyContact(contact1);
break
;
case
3
:
//刪除聯繫人
String idString=bf.nextLine();
operator.removeContact(idString);
operator.removeContact(idString);
break
;
case
4
:
//查看所有聯繫人
List<Contact> contacts=operator.checkContacts();
for
(Contact contact2 : contacts) {
System.out.println(contact2);
}
break
;
case
5
:
System.out.println(
"你已退出系統!"
);
System.exit(
0
);
break
;
default
:
System.out.println(
"輸入錯誤,請重新輸入!!!"
);
break
;
}
}
}
private
static
void
printMenu() {
System.out.println(
"======主菜單======"
);
System.out.println(
"1、添加聯繫人"
);
System.out.println(
"2、修改聯繫人"
);
System.out.println(
"3、刪除聯繫人"
);
System.out.println(
"4、查看所有聯繫人"
);
System.out.println(
"5、退出系統"
);
System.out.println(
"================"
);
}
}
|
到現在我們剩下的工作就是創建一個Operate類來實現該上述接口以完成其具體的功能,但在寫的過程中我們注意到喝多代碼一直重複着,比如講一個Document的對象寫入本地的xml文檔,不管是添加聯繫人操作還是刪除或者修改聯繫人的操作,這個時候爲了提高代碼的複用性,我們可以創建以XMLUtil工具類來簡化代碼,如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
|
package
com.gqx.Test;
import
java.io.FileNotFoundException;
import
java.io.FileOutputStream;
import
java.io.OutputStream;
import
javax.management.RuntimeErrorException;
import
org.dom4j.Document;
import
org.dom4j.DocumentException;
import
org.dom4j.io.OutputFormat;
import
org.dom4j.io.SAXReader;
import
org.dom4j.io.XMLWriter;
/*
* xml操作的工具類
*/
public
class
XMLUtil {
//寫出一個xml文件
public
static
void
write2xml(Document doc)
throws
Exception{
OutputStream out=
new
FileOutputStream(
"e:/contact.xml"
);
OutputFormat format=OutputFormat.createPrettyPrint();
format.setEncoding(
"utf-8"
);
XMLWriter writer=
new
XMLWriter(out,format);
writer.write(doc);
writer.close();
}
//讀取本地xml文件的方法
public
static
Document getDocument(){
Document doc;
try
{
doc =
new
SAXReader().read(
"e:/contact.xml"
);
return
doc;
}
catch
(DocumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
throw
new
RuntimeException(e);
}
}
}
|
完成這個操作後,這個時候可以來完成具體的核心操作了
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
|
package
com.gqx.Test;
import
java.io.File;
import
java.io.FileNotFoundException;
import
java.io.FileOutputStream;
import
java.io.OutputStream;
import
java.io.UnsupportedEncodingException;
import
java.util.ArrayList;
import
java.util.List;
import
org.dom4j.Document;
import
org.dom4j.DocumentException;
import
org.dom4j.DocumentHelper;
import
org.dom4j.Element;
import
org.dom4j.Node;
import
org.dom4j.io.OutputFormat;
import
org.dom4j.io.SAXReader;
import
org.dom4j.io.XMLWriter;
public
class
Operator
implements
ContactOperate {
@Override
public
void
addContact(Contact contact)
throws
Exception {
// TODO Auto-generated method stub
/**
* 添加聯繫人,把contact保存到xml文檔中
*/
File file=
new
File(
"e:/contact.xml"
);
Document doc=
null
;
Element rootElem=
null
;
if
(file.exists()) {
doc=
new
SAXReader().read(file);
rootElem=doc.getRootElement();
}
else
{
//如果沒有xml文件,創建xml文件
doc=DocumentHelper.createDocument();
rootElem=doc.addElement(
"contactList"
);
}
//添加contact標籤
Element contactElem=rootElem.addElement(
"contact"
);
contactElem.addAttribute(
"id"
, contact.getId());
contactElem.addElement(
"name"
).setText(contact.getName());
contactElem.addElement(
"sex"
).setText(contact.getSex());
contactElem.addElement(
"age"
).setText(contact.getAge());
contactElem.addElement(
"phone"
).setText(contact.getPhone());
contactElem.addElement(
"email"
).setText(contact.getEmail());
contactElem.addElement(
"qq"
).setText(contact.getQq());
/**
* 代碼中多處用到將document對象寫入xml文檔中,
* 此時可以加強代碼的複用性,寫一個xml的工具類,
* 其中一個方法便是將document轉化爲xml的靜態方法
*/
XMLUtil.write2xml(doc);
}
@Override
public
void
ModifyContact(Contact contact)
throws
Exception {
// TODO Auto-generated method stub
//根據xpath快速找到其屬性id爲xx的contact
//先讀取xml文件
Document doc=
new
SAXReader().read(
"e:/contact.xml"
);
//根據xpath快熟找到該節點
Element contactNode=(Element) doc.selectSingleNode(
"//contact[@id='"
+contact.getId()+
"']"
);
//根據標籤該文本
contactNode.element(
"name"
).setText(contact.getName());
contactNode.element(
"age"
).setText(contact.getAge());
contactNode.element(
"email"
).setText(contact.getEmail());
contactNode.element(
"phone"
).setText(contact.getPhone());
contactNode.element(
"sex"
).setText(contact.getSex());
XMLUtil.write2xml(doc);
}
@Override
public
void
removeContact(String id)
throws
Exception {
// TODO Auto-generated method stub
//先讀取xml文件
Document doc=XMLUtil.getDocument();
//根據xpath快熟找到該節點
Element contactNode=(Element) doc.selectSingleNode(
"//contact[@id='"
+id+
"']"
);
//刪除節點
contactNode.detach();
XMLUtil.write2xml(doc);
}
@Override
public
List<Contact> checkContacts() {
// TODO Auto-generated method stub
Document doc=XMLUtil.getDocument();
//創建list集合
List<Contact> list =
new
ArrayList<Contact>();
List<Element> conList=(List<Element>) doc.selectNodes(
"//contact"
);
for
(Element element : conList) {
Contact contact=
new
Contact();
contact.setId(element.attributeValue(
"id"
));
contact.setAge(element.elementText(
"age"
));
contact.setEmail(element.elementText(
"email"
));
contact.setName(element.elementText(
"name"
));
contact.setPhone(element.elementText(
"phone"
));
contact.setQq(element.elementText(
"qq"
));
contact.setSex(element.elementText(
"sex"
));
list.add(contact);
}
return
list;
}
}
|
注意:有時候在調試以上各種方法的時候,我們可以創建一個調試類,來對每一個具體的操作來調試,可以分別對接口中的每一個方法測試。這樣方便發現其中過程是否發生了錯誤:如
package com.gqx.Test; import java.util.List; import org.junit.Before; public class Test { Operator operator=null; //初始化這個對象的實例 @Before public void init(){ operator=new Operator(); } @org.junit.Test public void AddContact() throws Exception{ Contact contact=new Contact(); contact.setId("002"); contact.setAge("21"); contact.setEmail("[email protected]"); contact.setName("gqxing"); contact.setPhone("13455555"); contact.setQq("235346662"); contact.setSex("男"); operator.addContact(contact); } @org.junit.Test public void UpdateContact() throws Exception{ Contact contact=new Contact(); contact.setId("003"); contact.setAge("0"); contact.setEmail("[email protected]"); contact.setName("test"); contact.setPhone("0-00000000000"); contact.setQq("000000000000"); contact.setSex("男"); operator.ModifyContact(contact); } @org.junit.Test public void removeContact() throws Exception{ operator.removeContact("003"); } @org.junit.Test public void allContact() throws Exception{ List<Contact> contacts= operator.checkContacts(); for (Contact contact : contacts) { System.out.println(contact); } } }
寫在最後:實現多功能的操作,可以通過接口或者抽象類去理清其中的關係,避免代碼臃腫和雜亂,還有junit是一個很好的測試類。