XML解析
Dom4j工具
使用步骤:
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("标签名") //获取当前标签的指定名称的子标签的文本内容
Dom4j修改xml文档
(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()
SAX解析工具
核心的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开发编码相对复杂。 |
xPath技术
(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("454444@qq.com");
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("0000000@qq.com");
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是一个很好的测试类。

浙公网安备 33010602011771号