up:: XML使用Dom4j写追加XML文档
问题引入:把工资大于3000的员工提取出来;或者,编号为3310的员工信息提出来;难道要编写程序挨个遍历,然后提取?显然不可取,工作量太大;
XML有专门的查询工具:XPath;
一:XPath简介
XPath:是XML的查询语言,可以极大简化XML的查询和提取的过程;
1.XPath两种最常见的表达式:基本表达式;谓语表达式;
(1)XPath基本表达式
(2)XPath谓语表达式:在基本表达式的基础上,增加了额外的约束条件
2.在使用Dom4j,利用XPath查询时候,必须要先下载Jaxen的jar包;
发现,无法访问http://jaxen.codehaus.org/
解决办法:可以访问https://maven.aliyun.com/mvn/search;通过阿里提供的代码仓库找到需要的jar包:
二:XPath示例程序
1.准备的XML:
<?xml version="1.0" encoding="UTF-8"?>
<!-- 人力资源管理系统 --><!--xmlns:xsi的意思是告诉XML文档,我们的约束是使用Schema;xsi:noNamespaceSchemaLocation:指向xsd文件 -->
<hr xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="hr-schema.xsd">
<employee no="3301"> <!-- 标签和属性尽量起的有意义,做到见名知意 -->
<name>李刚</name>
<age>31</age>
<salary>4000</salary>
<department> <!-- 标签可以嵌套 -->
<dName>会计</dName>
<dAddress>4楼103室</dAddress>
</department>
</employee>
<employee no="3302">
<name>李四</name>
<age>29</age>
<salary>5000</salary>
<department>
<dName>工程部门</dName>
<dAddress>4楼105室</dAddress>
</department>
</employee>
<employee no="3303">
<name>王红</name>
<age>35</age>
<salary>3800</salary>
<department>
<dName>行政部门</dName>
<dAddress>3楼301室</dAddress>
</department>
</employee>
<employee no="3304">
<name>王华</name>
<age>28</age>
<salary>4300</salary>
<department>
<dName>行政部门</dName>
<dAddress>3楼301室</dAddress>
</department>
</employee>
<employee no="3305">
<name>刘铁</name>
<age>27</age>
<salary>3300</salary>
<department>
<dName>行政部门</dName>
<dAddress>3楼301室</dAddress>
</department>
</employee>
</hr>
2.查询的基本程序架构:
下面的核心是:
(1)List<Node> nodes = document.selectNodes(xpathExp); 核心查询方法,返回查询到的所有满足条件的Node列表; xpathExp就是XPath表达式
(2)emp.attributeValue(“no”):查询属性的方法;
(3)emp.elementText(“name”):查询标签值的方法;
public class XpathTest {
public void xpath(String xpathExp) {
String file = "e:/eclipse-workspace/xml/src/hr-schema.xml";
//(1) SAXReader是读取XML文件的核心类,用于将XML解析后以“树”的形式保存在内存中。
SAXReader reader = new SAXReader();
try {
// (2) SAXReader类的主要方法时read()方法,该方法返回一个Document对象;
Document document = reader.read(file);
// 返回的是Node的集合;为什么说是Node而不是Element?因为,XPath表达式不仅可以查询标签(Element),还可以查询属性(Attribute),Node是Element和Attribute的父类
List<Node> nodes = document.selectNodes(xpathExp);
for(Node node:nodes) { // 遍历查询到的满足条件的节点(Node)
Element emp = (Element)node; // 强制类型转换
System.out.println(emp.attributeValue("no")); // 获取节点的属性值;
System.out.println(emp.elementText("name")); // 获取节点的标签值
System.out.println(emp.elementText("age"));
System.out.println(emp.elementText("salary"));
System.out.println("==========================");
}
} catch (DocumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void main(String[] args) {
XpathTest testor = new XpathTest();
// testor.xpath("/hr/employee");
// testor.xpath("//employee");
// testor.xpath("//employee[salary>=4000]");
// testor.xpath("//employee[name='李四']"); // 用单引号
// testor.xpath("//employee[@no=3304]");
// testor.xpath("//employee[1]");
// testor.xpath("//employee[position()<4]");
testor.xpath("//employee[2] | //employee[4] | //employee[5]"); // 中间的竖杠的意思是把前后两个表达式的结果进行合并
}
}
3.在上面基本程序架构中,使用不同的XPath表达式,查询演示
举例子: 不同的XPath表达式,作为 selectNodes() 方法的参数,就会得到满足XPath表达式条件的一个集合 :List<Node> nodes = document.selectNodes(xpathExp);
(1)查询所有根节点(<hr>元素)下所有直接的子<employeegt;元素:“/hr/employee”
“/hr/employee”:会按照原XML的顺序,得到 <employeegt;不会乱顺序,这个不会乱顺序是指,只能获取<hrgt;的直接子标签的<employeegt;标签;
效果:全部打出来了
**(2)查询XML中所有的 <employeegt;元素:
“//employee”** 和(1)结果相同,所有 <employeegt;全部打出来了;“//employee”:不管<employeegt;这个标签在哪儿,也不管其是不是<hrgt;的直接子标签,只要是XML中<emppoyeegt;标签都获取
效果:
(3)获取所有“ <salarygt;元素值大于等于4000”的<employeegt;元素:“//employee[salary>=4000]”
统计所有工资小于4000的工人,salary是employee的子节点;下面 利用[ ]添加了查询的筛选条件,这比我们在Java中写代码筛选高效的多;
结果:
(4)查询, <namegt;元素值为“李四”的,<employeegt;元素:“//employee[name=‘李四’]”
提取“李四”的信息(即提取某一项信息), 利用[ ]添加了查询的筛选条件;
结果:
(5)查询,属性等于某值的,所有 <employeegt;属性:“//employee[@no=3304]”
通过工号获取某人的信息;涉及到属性了, 属性使用@;
结果:
(6)获得第一个员工的信息:“//employee[1]”
结果:返回了XML中第一个<employeegt;的信息
(7)获得最后一个员工的信息:“//employee[last()]”
结果:
(8)获取前三个员工:“//employee[position() <4]”
结果:
(9)提取第二个和第四个员工和第五个员工:“//employee[2] | //employee[4] | //employee[5]”
XPath支持组合表达式,用到了“|”;
结果:
注意:
(1)注意扩展到一般,引申;
(2)最重要的是,通过List <Nodegt; nodes = document.selectNodes(xpathExp); ,利用合适xpath表达式获得Node集合;本篇博客为了方便展示结果,采用了打印employee节点的子节点的值的做法;在实际中,可能具体的应用可能不同,但通过Xpath获得List<Nodegt;是最重要的;
(附)/:代表根;//:代表全文搜索,而不管其嵌套顺序和结果;[ ]:代表子元素;@:代表属性;(20210101)