dom4j是阿帕奇出品的一个开源 XML 解析包,是一个简单、灵活的开源库,用来读写XML文件的。dom4j使用接口和抽象基类,是jdom的升级品,dom4j的API相对要复杂一些但比jdom更好的灵活性。
Dom4j是完美支持Xpath,具有性能优异、功能强大和极易使用的特点。
XPath 是一门在 XML 文档中查找信息的语言。
Xpath包下载地址:http://www.cafeconleche.org/jaxen
Xpath maven发送导入依赖:
org.dom4j dom4j 版本号
dom4j包下载地址:http://dom4j.github.io/
Xpath maven方式导入依赖:
jaxen jaxen 版本号
XPath 使用路径表达式在 XML 文档中选取节点。
表达式 | 描述 |
---|---|
标签名 | 选取此标签的所有子节点。 |
/ | 从根节点选取(取子节点)。 |
// | 从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置(取子孙节点)。 |
. | 选取当前节点。 |
… | 选取当前节点的父节点。 |
@ | 选取属性。 |
谓语用来查找某个特定的节点或者包含某个指定的值的节点。
谓语被嵌在方括号[ ]中。
路径表达式 | 结果 |
---|---|
/标签1/标签2[数字] | 选取属于标签1 子元素的第‘数字’个 标签2元素。类似数组 |
/标签1/标签2[last()] | 选取属于 标签1 子元素的最后一个 标签2 元素。 |
/标签1/标签2[position()< 3] | 选取最前面的两个属于 标签1 元素的子元素的 标签2 元素。 |
//标签[@属性名] | 选取所有拥有名为 ‘属性名’ 的属性的 标签 元素。 |
//标签[@属性名=‘属性值’] | 选取所有 标签 元素,且这些元素拥有值为 ‘属性名=‘属性值’。 |
XPath 通配符可用来选取未知的 XML 元素。
通配符 | 描述 |
---|---|
* | 匹配任何元素节点。 |
@* | 匹配任何属性节点。 |
node() | 匹配任何类型的节点。 |
通过在路径表达式中使用"|"运算符,您可以选取若干个路径。
例如
//标签1 | //标签2
选取文档中的所有 标签1 和 标签2 元素。
接口 | 功能 |
---|---|
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.Cloneableinterface org.dom4j.Nodeinterface org.dom4j.Attributeinterface org.dom4j.Branchinterface org.dom4j.Documentinterface org.dom4j.Elementinterface org.dom4j.CharacterDatainterface org.dom4j.CDATAinterface org.dom4j.Commentinterface org.dom4j.Textinterface org.dom4j.DocumentTypeinterface org.dom4j.Entityinterface org.dom4j.ProcessingInstruction
首先需要导入依赖
org.dom4j dom4j 2.1.3 jaxen jaxen 1.2.0 junit junit 4.13.2 test
配置文件如下
解析步骤
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标签,进行处理
@Testpublic void testMybatisConfigXML() throws DocumentException {//1.使用Dom4j创建reader对象SAXReader reader = new SAXReader();//2.通过类加载器获取Myabtis的配置文件输入流InputStream config_stream = ClassLoader.getSystemClassLoader().getResourceAsStream("mybatis-config.xml");//3.读XML文件,返回一个文档对象documentDocument 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 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 mappers = document.selectNodes(xpath);mappers.forEach(mapper -> {Element mapperElt = (Element) mapper;String resource = mapperElt.attributeValue("resource");//到时候应该是动态解析这个资源文件System.out.println(resource);});}
结果
映射文件如下
insert into t_mybatisvalue(#{deptno},#{dname},#{loc})
解析步骤
1.使用Dom4j创建reader对象
2.通过类加载器获取Myabtis的配置文件输入流
3.读XML文件,返回一个文档对象document
4.对标签进行处理
(1)获取根标签的namespace
(2)获取mapper的所有子节点
@Testpublic void testSqlMapperXML() throws DocumentException {//1.使用Dom4j创建reader对象SAXReader reader = new SAXReader();//2.通过类加载器获取SqlMapper的配置文件输入流//mybatis是动态获取的,这里是测试写死InputStream SqlMapper_stream = ClassLoader.getSystemClassLoader().getResourceAsStream("DeptMapper.xml");//3.读XML文件,返回一个文档对象documentDocument document = reader.read(SqlMapper_stream);//4.对标签进行处理//(1)获取根标签的namespaceString xpath = "/mapper";Element mapper = (Element) document.selectSingleNode(xpath);String namespace = mapper.attributeValue("namespace");System.out.println(namespace);//(2)获取mapper的所有子节点List elements = mapper.elements();elements.forEach(element -> {String id = element.attributeValue("id");String resultType = element.attributeValue("resultType");//没有这个属性会自动返回nullString sql = element.getTextTrim();//表示获取标签内容,而且去除前后空白System.out.println(sql);//转换sql语句,使用正则表达式把#{}的内容替换成占位符?String newsql = sql.replaceAll("#\\{[0-9A-Za-z_$]*}", "?");System.out.println(newsql);});}
结果