Java中xml解析---dom4j

xml的解析方式

解析方式为两种:

  • DOM(Document Object Model)解析:将整个xml文件加载到内存,形成一个DOM树

    • 优点:能获取到整个DOM树的完整信息,通过document对象来对DOM树进行CRUD操作
    • 缺点:由于是直接加载整个xml文件,当形成的DOM树太大时,会占用较多的内存资源
  • SAX(Simple API For Xml)解析:对xml进行逐行解析,逐行加载,需要哪行就加载哪行

    • 优点:逐行加载,不太占用内存资源
    • 缺点:无法获取整个DOM树对象,只能对xml数据进行查询,不能增删

xml常用的解析器

jaxp:是SUN公司提供的xml解析器,支持dom和sax这两种方式的解析

dom4j:是开源组织提供的xml解析器,性能是优于SUN公司提供的解析器的, 基于dom和sax这两种方式的综合解析方式

jsoup:主要是用来解析html的,但是由于html和xml的结构是一样的,所以也可以用来解析xml

使用demo4j对xml文件进行CRUD

首先获取根标签对象,对DOM树操作是基于root来进行的:

1
2
3
4
5
6
7
8
9
10
11
12
public class demo{
private static Document document;
private static Element root;

public static void main(String[] args) throws Exception{
SAXReader saxReader = new SAXReader();
// read()是个重载方法, 可以通过多种方式来获取Document对象
// document = saxReader.read(demo.class.getClassLoader().getResourceAsStream("JDBC.xml"));
document = saxReader.read(new File(demo.class.getClassLoader().getResource("JDBC.xml").getPath()));
root = document.getRootElement();
}
}

读取JDBC.xml中的数据库信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public static HashMap<String, String> select(){
HashMap<String, String> hashMap = new HashMap<>();

// 方法一
/*
List<Element> elementList = root.elements(); // 获取根标签下的所有子标签,返回值为一个列表
for(Element e:elementList){
if(e.attributeValue("id").equals("mysql")){
for(Element e1:e.elements()){
hashMap.put(e1.getName(), e1.getText());
}
}
} // 获取子标签中所有的标签信息,将标签名和标签内容组成键值对放入双列集合中
return hashMap;
*/

// 方法二
Element element = root.elementByID("mysql"); // 获取指定id的子标签,返回值为标签对象
for(Element e:element.elements()){
hashMap.put(e.getName(), e.getText());
}
return hashMap;
}

在对xml文件进行增删改时,修改的是加载在内存中DOM树对象,在修改完成后,还要将DOM树对象写入到xml文件中:

1
2
3
4
5
6
7
8
9
10
11
public static void saveXML(String path){

OutputStream os = new FileOutputStream(path); // 创建字节输出流对象,也可以使用字符输出流
OutputFormat format = OutputFormat.creatPrettyPrint(); // 创建输出格式化对象

XMLWriter writer = new XMLWriter(os, format); // 创建XML字符输出流对象
writer.write(document); // 将被修改的DMO树对象写入的指定文件中
writer.close();


}

为JDBC.xml添加一个数据库信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public static void add(){
Element element = root.addElement("database"); // 在根标签下添加一个子标签
element.setAttributeValue("ID", "oracle"); // 为该子标签添加属性

Element driverElement = element.addElement("driver"); // 在子标签下再创建子标签,并添加文本内容
driverElement.setText("com.oracle.jdbc.driver");

Element urlElement = element.addElement("url");
urlElement.setText("jdbc:oracle://localhost:1521/testDb");

Element userElement = element.addElement("user");
userElement.setText("root");

Element pwdElement = element.addElement("pwd");
pwdElement.setText("root");

saveXML(demo.class.getClassLoader().getResource("JDBC.xml").getPath()); // 将原XML覆盖

}

修改JDBC.xml中的数据库信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public static void update(){

Element element = root.elementByID("oracle");

for(Element e:element.elements()){
if(e.getName().equals("pwd")){
e.setAttributeValue("name", "pwd");
e.setText("123456");
}
}

saveXML(demo.class.getClassLoader().getResource("JDBC.xml").getPath());

}

删除JDBC.xml中的数据信息:

1
2
3
4
5
6
7
8
9
10
11
public static void delete(){

List<Element> elementsList = root.elements();
for(Element e:elementList){
if (e.attributeValue("ID").equals("oracle")){
root.remove(e);
}
} // 将整个子标签全部删除

saveXML(demo.class.getClassLoader().getResource("JDBC.xml").getPath());
}

通过XPATH的方式来获取标签对象

上面是通过根标签来获取DOM树中的node节点,dom4j还提供了以XPATH的方式来获取指定标签,这种方式更为灵活:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class demo{

public static void main(String[] args){
SAXReader saxReader = new SAXReader();
Document document = saxReader.read(demo.class.getClassLoader().getResourceAsStream("JDBC.xml"));

List<Node> nodesList = document.selectNodes("/databases"); // 获取根标签
List<Node> nodesList1 = document.selectNodes("//database"); // 获取所有的database标签
List<Node> nodesList2 = document.selectNodes("//database[@ID='mysql']"); //获取所有ID为Mysql的database标签
Node node = document.selectSingleNode("//user[@name='username']"); //获取name为username的一个user标签

System.out.println(node.getName()); // 打印节点的标签名
System.out.println(node.getText()); // 打印节点的内容
}
}