DOM文档对象模型

  • DOM(Document Object Model)定义了访问和操作XML文档的标准方法,DOM把XML文档作为树结构来查看,能够通过DOM树来读写所有的元素
    image-20220413185706029

Dom4j的概念

  • Dom4j是一个易用的、开源的库,用于解析XML,它应用于Java平台,具有性能优异、功能强大和极其亿使用的特点
  • Dom4j将XML视为Document对象
  • XML标签被Dom4j定义为Element(元素)对象

Dom4j解析读取XML文件实例

在idea中创建java工程,导入dom4j的jar包

在idea中:文件→项目结构→模块→依赖→导入jar包

image-20220413210150911

创建xml文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?xml version="1.0" encoding="UTF-8" ?>
<!--人力资源管理系统-->
<hr xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="hr-schema.xsd">
<employee no="3309">
<name>张三</name>
<age>19</age>
<salary>4000</salary>
<department>
<dname>会计部</dname>
<address>XX大厦-B103</address>
</department>
</employee>

<employee no="3310">
<name>李四</name>
<age>23</age>
<salary>4000</salary>
<department>
<dname>工程部</dname>
<address>XX大厦-B104</address>
</department>
</employee>
</hr>

创建解析xml文件的java文件,并导入dom4jjar包

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
package com.java.dom4j;//导入dom4jjar包

import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.util.List;

public class HrReader {//编写一个内部类
public void readXml(){//编写解析XML文件的方法
//定义xml文件的位置
String file="D:\\Documents\\java\\javaweb\\XML\\src\\XML\\hr.xml";
//SAXReader类是读取XML文件的核心类,用于将XML解析后以"树"的形式保存在内存中
SAXReader reader =new SAXReader();
try {
Document document =reader.read(file);//读取文件
//获取XML文档的根节点,即hr标签
Element root= document.getRootElement();
//elements方法用于获取指定的标签集合,这里获取到主节点及其子节点中的集合
List<Element> employees = root.elements("employee");
for (Element employee:employees){//循环遍历输出主节点中的内容
//element方法用于获取唯一的子节点对象
Element name = employee.element("name");
String empName=name.getText();//getText()方法用于获取标签文本
System.out.println(empName);
//elementText获取employee主节下的其他子节点,这里的employee是获得employee节点的集合
System.out.println(employee.elementText("age"));
System.out.println(employee.elementText("age"));
System.out.println(employee.elementText("salary"));
Element department=employee.element("department");//获取到employee下的depart标签
System.out.println(department.elementText("dname"));//获取到department标签下的子标签
System.out.println(department.elementText("address"));

//attribute方法来获取employee下的no属性
Attribute attribute =employee.attribute("no");
System.out.println(attribute.getText());

}
} catch (DocumentException e) {
e.printStackTrace();
}
}

public static void main(String[] args) {
HrReader reader =new HrReader();//创建类的实例
reader.readXml();//调用实例类中的方法
}
}

Dom4j更新写入XML文件

大致步骤:获取文件→获取根节点→在根节点中添加属性,子节点→核心操作字节输出流,将其写入到xml文件中

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
package com.java.dom4j;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;

public class HrWrite {
public void writeXml(){
String file="D:\\Documents\\java\\javaweb\\XML\\src\\XML\\hr.xml";
//SAXReader类是读取XML文件的核心类,用于将XML解析后以"树"的形式保存在内存中
SAXReader reader = new SAXReader();
try {
//读取文件
Document document = reader.read(file);
//获取根节点 hr
Element root = document.getRootElement();
//在根节点下,添加employee子节点
Element employee=root.addElement("employee");
//在employee节点下增加属性no
employee.addAttribute("no","3311");
//在employee节点下增加name,age,salary节点,并增加其值
Element name = employee.addElement("name");
name.setText("王丙");
employee.addElement("age").setText("20");
employee.addElement("salary").setText("3800");
//在employee节点写入department节点与子节点
Element depart=employee.addElement("department");
depart.addElement("dname").setText("工程部");
depart.addElement("address").setText("XX大厦-B105");

//写文件的核心操作,file代表的是获取到的xml文件
Writer writer = new OutputStreamWriter(new FileOutputStream(file),"UTF-8");
document.write(writer);
writer.close();
} catch (Exception e) {//提升到Exception异常就不会报错了
e.printStackTrace();
}
}

public static void main(String[] args) {
HrWrite hrWrite= new HrWrite();
hrWrite.writeXml();

}
}

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
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hr SYSTEM "hr.dtd"><!--人力资源管理系统-->
<hr>
<employee no="3309">
<name>张三</name>
<age>31</age>
<salary>4000</salary>
<department>
<dname>会计部</dname>
<address>XX大厦-B103</address>
</department>
</employee>

<employee no="3310">
<name>李四</name>
<age>23</age>
<salary>4000</salary>
<department>
<dname>工程部</dname>
<address>XX大厦-B104</address>
</department>
</employee>
<!--w-->
<employee no="3311">
<name>王丙</name>
<age>20</age>
<salary>3800</salary>
<department>
<dname>工程部</dname>
<address>XX大厦-B105</address>
</department>
</employee>
</hr>

Xpath路径表达式

  • Xpath路径表达式是XML文档中查找数据的语言
  • 掌握Xpath可以极大的提高在提取数据时的开发效率
  • 学习Xpath的本质就是掌握各种形式表达式的使用技巧

Xpath的基本表达式

最常用的基本表达式

表达式 描述
nodename 选取此节点下所有子节点
/ 从根节点选取
// 从匹配选择的当前节点选择文档中的节点,而不考虑他们的位置
. 选取当前的节点
.. 选取但前节点的父节点
@ 选取属性

Xpath基本表达式案例

路径表达式 结果
bookstore 选取bookstore元素的所有子节点
/bookstore 选取根元素bookstore。注释:假如路径起始于正斜杆(/),则此路径始终代表到某元素的绝对路径
bookstore/book 选取属于bookstore的子元素中所有book元素
//book 选取所有book子元素,而不管他们在文档中的位置
bookstore//book 选择属于bookstore元素的后代的所有book元素,而不管他们位于bookstore之下的什么位置
//@long 选取名为lang的所有属性

Xpath谓语表达式

路径表达式 结果
/bookstore/book[1] 选取属于bookstore子元素的第一个book元素
/bookstore/book[last()] 选取属于bookstore子元素的最后一个book元素
/bookstore/book[last()-1] 选取属于bookstore子元素的倒数第二个book元素
/bookstore/book[position()<3] 选取最前面的两个属于bookstore元素的子元素的book元素
//title[@lang] 选取所有拥有名为lang属性的title元素
//title[@lang=’eng’] 选取所有的title元素,且这些元素拥有lang属性=eng
/bookstore/book[price>35.00] 选取bookstore元素的所有book元素下的price元素,且price元素的值要大于35.00
/bookstore/book[price>35.00]/title 选取bookstore元素中的book元素的所有title元素,且其中的price元素的值须大于35.00

Xpath实验室

Xpath工具之Jaxen的介绍

  • Jaxen是一个Java编写的开源的Xpath库。这是适应多种不同的对象模型,包括DOM,XOM,dom4j和JDOM
  • Dom4j底层依赖Jaxen实现Xpath查询
  • Jaxen 下载地址:jaxen.codeehaus.org
  • maven.aliyun.com:阿里云的代码仓库,可以找到我们想要的jar包

Xpath实验

利用Xpath来获取xml文件并利用Xpath表达式来对其进行操作

核心方法执行xpath表达式xpathExp,node节点是Element(元素),attribute(属性)方法的父类

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
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hr SYSTEM "hr.dtd"><!--人力资源管理系统-->
<hr>
<employee no="3301">
<name>张三</name>
<age>31</age>
<salary>4000</salary>
<department>
<dname>会计部</dname>
<address>XX大厦-B103</address>
</department>
</employee>

<employee no="3302">
<name>李四</name>
<age>23</age>
<salary>4000</salary>
<department>
<dname>工程部</dname>
<address>XX大厦-B104</address>
</department>
</employee>
<employee no="333">
<name>王丙</name>
<age>20</age>
<salary>3800</salary>
<department>
<dname>工程部</dname>
<address>XX大厦-B105</address>
</department>
</employee>
</hr>
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
//Xpath获取xml文件中节点属性,并利用Xpath表达式来调用
package com.java.dom4j;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;

import javax.xml.xpath.XPath;
import java.util.List;

public class XPathTestor {
public void xpath(String xpathExp){
String file="D:\\Documents\\java\\javaweb\\XML\\src\\XML\\hr.xml";//获取文件
//SAXReader类是读取XML文件的核心类,用于将XML解析后以"树"的形式保存在内存中
SAXReader reader = new SAXReader();
try {
Document document =reader.read(file);//读取文件返回document类型
//核心方法执行xpath表达式xpathExp,node节点是Element(元素),attribute(属性)方法的父类
List<Node> nodes =document.selectNodes(xpathExp);
for (Node node:nodes){
//循环遍历获取元素与节点
Element emp = (Element) node;//强制转换 将node父元素转换为子类Element元素执行子类中的方法
System.out.println(emp.attributeValue("no"));//获取到no属性并输出
System.out.println(emp.elementText("name"));//获取到name子元素并输出
System.out.println(emp.elementText("age"));//获取到age子元素并输出
System.out.println(emp.elementText("salary"));//获取到salary子元素并输出
Element department = emp.element("department");//emp代表的是xml文件中的所有元素与属性的集合,这里是获取emp集合中的department元素并赋予给depatment的实例名
System.out.println(department.elementText("dname"));//获取到department下dname子元素
System.out.println(department.elementText("address"));//获取到department下address子元素
System.out.println("-------------------------------");
}
} catch (DocumentException e) {
e.printStackTrace();
}

}

public static void main(String[] args) {
XPathTestor xPathTestor = new XPathTestor();
// xPathTestor.xpath("/hr/employee");//获取到hr根标签下的employee子节点下的属性并输出(方法中有输出的方法),/表示要从主节点下按顺序获取
// xPathTestor.xpath("//employee");//代表的是所有的employee标签
// xPathTestor.xpath("//employee[salary<4000]");//代表的是所有empolyee标签下的所有的salary小于4000的结果并输出
// xPathTestor.xpath("//employee[name='王丙']");
// xPathTestor.xpath("//employee[@no=3301]");//获取到所有标签为employee的标签,且筛选no属性值为3301的结果
// xPathTestor.xpath("//employee[1]");//获取到第一个employee节点下的标签(方法中有写获取到的节点)
//xPathTestor.xpath("//employee[last()]");//获取到最后一个employee节点下的标签(方法中有写获取到的节点)
//xPathTestor.xpath("//employee[position()<=2]");//获取到employee下所有的子元素,且筛选前两个位置
//xPathTestor.xpath("//employee[1] | //employee[3]");//获取到第一个与第三个employee标签下的标签中的内容

}
}