1、dom4j简介
dom4j是阿帕奇出品的一个开源 XML 解析包,是一个简单、灵活的开源库,用来读写XML文件的。dom4j使用接口和抽象基类,是jdom的升级品,dom4j的API相对要复杂一些但比jdom更好的灵活性。
Dom4j是完美支持Xpath,具有性能优异、功能强大和极易使用的特点。
XPath 是一门在 XML 文档中查找信息的语言。
Xpath包下载地址:http://www.cafeconleche.org/jaxen
Xpath maven发送导入依赖:
<dependency>
<groupId>org.dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>版本号</version>
</dependency>
dom4j包下载地址:http://dom4j.github.io/
Xpath maven方式导入依赖:
<dependency>
<groupId>jaxen</groupId>
<artifactId>jaxen</artifactId>
<version>版本号</version>
</dependency>
2、XPath基本语法
选取节点语法
XPath 使用路径表达式在 XML 文档中选取节点。
表达式 | 描述 |
---|---|
标签名 | 选取此标签的所有子节点。 |
/ | 从根节点选取(取子节点)。 |
// | 从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置(取子孙节点)。 |
. | 选取当前节点。 |
… | 选取当前节点的父节点。 |
@ | 选取属性。 |
谓语语法
谓语用来查找某个特定的节点或者包含某个指定的值的节点。
谓语被嵌在方括号[ ]中。
路径表达式 | 结果 |
---|---|
/标签1/标签2[数字] | 选取属于标签1 子元素的第‘数字’个 标签2元素。类似数组 |
/标签1/标签2[last()] | 选取属于 标签1 子元素的最后一个 标签2 元素。 |
/标签1/标签2[position()< 3] | 选取最前面的两个属于 标签1 元素的子元素的 标签2 元素。 |
//标签[@属性名] | 选取所有拥有名为 ‘属性名’ 的属性的 标签 元素。 |
//标签[@属性名=‘属性值’] | 选取所有 标签 元素,且这些元素拥有值为 ‘属性名=‘属性值’。 |
选取未知节点语法
XPath 通配符可用来选取未知的 XML 元素。
通配符 | 描述 |
---|---|
* | 匹配任何元素节点。 |
@* | 匹配任何属性节点。 |
node() | 匹配任何类型的节点。 |
选取若干路径语法
通过在路径表达式中使用"|"运算符,您可以选取若干个路径。
例如
//标签1 | //标签2
选取文档中的所有 标签1 和 标签2 元素。
3、DOM4J接口
接口 | 功能 |
---|---|
Attribute | 定义了 XML 的属性。 |
Branch | Branch接口定义了节点的常见行为,这些节点可以包含子节点(内容),例如XML元素和文档。 |
CDATA | 定义了 XML CDATA 区域,指CDATA 部分中的所有内容都会被解析器忽略。 |
CharacterData | 是一个标识接口,标识基于字符的节点。如CDATA,Comment, Text. |
Comment | 定义了 XML 注释的行为 |
Document | 定义了XML 文档 |
DocumentType | 定义 XML DOCTYPE 声明 |
Element | 定义XML 元素 |
ElementHandler | 定义了Element 对象的处理器 |
ElementPath | 被 ElementHandler 使用,用于取得当前正在处理的路径层次信息 |
Entity | 定义 XML entity |
Node | 为dom4j中所有的XML节点定义了多态行为 |
NodeFilter | 定义了在dom4j 节点中产生的一个滤镜或谓词的行为(predicate) |
ProcessingInstruction | 定义 XML 处理指令 |
Text | 定义 XML 文本节点 |
Visitor | 用于实现 Visitor模式 |
XPath | 在分析一个字符串后会提供一个 XPath 表达式 |
接口之间的继承关系如下:
interface java.lang.Cloneable
interface org.dom4j.Node
interface org.dom4j.Attribute
interface org.dom4j.Branch
interface org.dom4j.Document
interface org.dom4j.Element
interface org.dom4j.CharacterData
interface org.dom4j.CDATA
interface org.dom4j.Comment
interface org.dom4j.Text
interface org.dom4j.DocumentType
interface org.dom4j.Entity
interface org.dom4j.ProcessingInstruction
4、使用DOM4J解析Mybatis配置文件
首先需要导入依赖
<!--dem4j依赖-->
<dependency>
<groupId>org.dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>2.1.3</version>
</dependency>
<!--jaxen依赖-->
<dependency>
<groupId>jaxen</groupId>
<artifactId>jaxen</artifactId>
<version>1.2.0</version>
</dependency>
<!--junit依赖-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
配置文件如下
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<!--mysql数据库连接信息-->
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mydbtest"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<mappers>
<!--指定Mapper.xml文件的路径,resource是在类的根资源路径下查找-->
<mapper resource="DeptMapper.xml"/>
<mapper resource="CarMapper2.xml"/>
<mapper resource="CarMapper3.xml"/>
</mappers>
</configuration>
解析步骤
1.使用Dom4j创建reader对象
2.通过类加载器获取Myabtis的配置文件输入流
3.读XML文件,返回一个文档对象document
4.对标签进行处理
4.1获取默认的环境,因为将来有可能配置多个环境
(1)获取environments的default的值
(2)通过defalt获取默认environment
4.2处理默认环境的配置
(1)获取事务管理器类型
(2)获取数据源类型
(3)处理dataSource下的所有子节点
5.获取所有的Mapper标签,进行处理
@Test
public void testMybatisConfigXML() throws DocumentException {
//1.使用Dom4j创建reader对象
SAXReader reader = new SAXReader();
//2.通过类加载器获取Myabtis的配置文件输入流
InputStream config_stream = ClassLoader.getSystemClassLoader().getResourceAsStream("mybatis-config.xml");
//3.读XML文件,返回一个文档对象document
Document document = reader.read(config_stream);
//4.对标签进行处理
//4.1获取默认的环境,因为将来有可能配置多个环境
//(1)获取environments的default的值
//xpath是做标签匹配路径,能够让我们快捷定位XML文件的标签
String xpath = "/configuration/environments";//这个意思是从根开始找标签configuration,然后找environments
//通过标签匹配路径获取节点,这样就获取到了environments这个节点,返回是Node,Element是Node的子类,方法更多,使用更方便
Element environments = ((Element) document.selectSingleNode(xpath));
//通过attributeValue获取default的值
String defalt = environments.attributeValue("default");
//(2)通过defalt获取默认environment
//xpath是可以通过属性获取标签的,语法是 标签[@属性名=属性值]
xpath = "/configuration/environments/environment[@id='"+defalt+"']";
Element environment = (Element) document.selectSingleNode(xpath);
//4.2处理默认环境的配置
//(1)获取事务管理器类型
//获取environment下的transactionManager标签,element用来获取孩子节点
Element transactionManager = environment.element("transactionManager");
//获取事务管理器的类型
String transactionType = transactionManager.attributeValue("type");
System.out.println("事务管理器的类型:" + transactionType);
//(2)获取数据源类型
Element dataSource = (Element) environment.element("dataSource");
String dataSourceType = dataSource.attributeValue("type");
System.out.println("数据源类型:" + dataSourceType);
//(3)处理dataSource下的所有子节点
List<Element> propertys = dataSource.elements();
propertys.forEach(propertysElt -> {
String name = propertysElt.attributeValue("name");
String value = propertysElt.attributeValue("value");
//mybatis到时候会用map进行存取
System.out.println(name + "=" + value);
});
//5.获取所有的Mapper标签,进行处理
//不想从根路径下获取,想从某个标签的所有标签,xpath的语法是 “//标签”
xpath = "//mapper";
List<Node> mappers = document.selectNodes(xpath);
mappers.forEach(mapper -> {
Element mapperElt = (Element) mapper;
String resource = mapperElt.attributeValue("resource");
//到时候应该是动态解析这个资源文件
System.out.println(resource);
});
}
结果
5、使用DOM4J解析映射文件
映射文件如下
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="dept">
<!--id是这条语句的唯一标识。这个id就代表了这条SQL语句-->
<insert id="insertDept">
insert into t_mybatis
value(#{deptno},#{dname},#{loc})
</insert>
<select id="selectById" resultType="com.pojo.Dept">
select * from t_mybatis where deptno=#{deptno}
</select>
</mapper>
解析步骤
1.使用Dom4j创建reader对象
2.通过类加载器获取Myabtis的配置文件输入流
3.读XML文件,返回一个文档对象document
4.对标签进行处理
(1)获取根标签的namespace
(2)获取mapper的所有子节点
@Test
public void testSqlMapperXML() throws DocumentException {
//1.使用Dom4j创建reader对象
SAXReader reader = new SAXReader();
//2.通过类加载器获取SqlMapper的配置文件输入流
//mybatis是动态获取的,这里是测试写死
InputStream SqlMapper_stream = ClassLoader.getSystemClassLoader().getResourceAsStream("DeptMapper.xml");
//3.读XML文件,返回一个文档对象document
Document document = reader.read(SqlMapper_stream);
//4.对标签进行处理
//(1)获取根标签的namespace
String xpath = "/mapper";
Element mapper = (Element) document.selectSingleNode(xpath);
String namespace = mapper.attributeValue("namespace");
System.out.println(namespace);
//(2)获取mapper的所有子节点
List<Element> elements = mapper.elements();
elements.forEach(element -> {
String id = element.attributeValue("id");
String resultType = element.attributeValue("resultType");//没有这个属性会自动返回null
String sql = element.getTextTrim();//表示获取标签内容,而且去除前后空白
System.out.println(sql);
//转换sql语句,使用正则表达式把#{}的内容替换成占位符?
String newsql = sql.replaceAll("#\\{[0-9A-Za-z_$]*}", "?");
System.out.println(newsql);
});
}
结果