dom4j解析XML文件

news2024/11/24 17:42:17

 主要为了讲解Mybatis中如何用dom4j解析XML,这里当作dom4j解析.XML文件的练习

引入mybatis配置文件和一个.xml文件  都是.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!--
       定义一些键值对,可以在当前文件中通过${}来使用,也可以在当前项目任意的mapper.xml文件中使用(就是下面指定的mapper文件)
       resource:指定外部文件
   -->
<!--    <properties resource="jdbc.properties">-->
<!--        <property name="aaaa" value="bbbb"/>-->
<!--    </properties>-->
<!--    <settings>-->
        <!--
        默认开启一级缓存,默认是SESSION      可选值:SESSION|STATEMENT
        如果value配置成STATEMENT,去掉一级缓存,每次都会去查,一般不配置这个
        -->
<!--        <setting name="localCacheScope" value="true"/>-->
        <!--
        开启日志
            SLF4J:需要引入SLF4J logback 如果用这个,想自己配置配置文件的话必须叫logback.xml或logback-test.xml
            LOG4J   log4j
            LOG4J2:以上三种,同一个作者   log4j2
            STDOUT_LOGGING:标准日志,Mybatis本身实现
        -->
<!--        <setting name="logImpl" value="SLF4J"/>&lt;!&ndash;如果用STDOUT_LOGGING需要配置一下,如果用其他的不用配置,引入依赖即可&ndash;&gt;-->
        <!-- 开启驼峰,开启后,只要数据库字段和对象属性名字母相同,无论中间加多少下划线都可以识别 -->
<!--        <setting name="mapUnderscoreToCamelCase" value="true" />-->
<!--        &lt;!&ndash;开启二级缓存&ndash;&gt;-->
<!--        <setting name="cacheEnabled" value="true"/>-->
<!--        &lt;!&ndash;默认false 配置返回为null的列&ndash;&gt;-->
<!--        <setting name="callSettersOnNulls" value="true"/>-->
<!--        &lt;!&ndash;默认false 配置当查询的列为null值时候 返回的user为null&ndash;&gt;-->
<!--        <setting name="returnInstanceForEmptyRow" value="true"/>-->
<!--        &lt;!&ndash;默认是true 使用编译参数&ndash;&gt;-->
<!--        <setting name="useActualParamName" value="true"/>-->
        <!--
        默认SIMPLE 可以选择REUSE BATCH 如果全局配置的话显然不是很好,因此,在需要批量的时候通过其他方式修改
        还是让它保持默认的SIMPLE,不去修改它
        -->
        <!--        <setting name="defaultExecutorType" value="BATCH"/>-->
<!--    </settings>-->
    <!--
       environments:数据库环境配置
       default:默认使用哪个库
       id:指定使用的数据库id
   -->
    <environments default="development">
        <environment id="development">
            <!--
                mybatis提供了两种事务管理机制
                1.JDBC(可小写)事务管理器:mybatis框架自己管理事务,实际就是采用原生JDBC代码管理事务
                    好比写JDBC时: conn.setAutoCommit(false);
                                ......业务处理......
                                conn.commit();手动提交
                2.MANAGED(可小写)事务管理器
                    mybatis不再管理事务,事务交给其他容器负责:例如Spring
                    但是这里用MANAGED,因为没有容器好比事务没有开启,就会变成没有事务这回事,直接干了
            -->
            <transactionManager type="JDBC"/>
            <!--
                dataSource:数据源
                type="POOLED",使用连接池
                type="UNPOOLED",不使用连接池
                type="JNDI",JNDI – 这个数据源实现是为了能在如 EJB 或应用服务器这类容器中使用,容器可以集中或在外部配置数据源,然后放置一个 JNDI 上下文的数据源引用。这种数据源配置只需要两个属性
            -->
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://xxxxxxxxxxxxxxxxxxxxxxx"/>
                <property name="username" value="xxxxx"/>
                <property name="password" value="xxxxxx"/>

            </dataSource>
        </environment>
    </environments>
    <mappers>
        <!--resource属性会自动从类的根路径下开始查找资源-->
        <!--
        1.<package name="包名"> 标签用于自动扫描指定包下的映射文件,要求映射文件名和接口名保持一致,并且映射文件(.xml)和接口需要在同一个包中,否则会报错。
        2.<mapper class=""> 标签的class属性用于注册映射文件,同样要求映射文件名和接口名保持一致,并且映射文件(.xml)和接口需要在同一个包中,否则会报错。
        3.<mapper resource="org/xx/demo/mapper/xx.xml"/> 标签用于注册映射文件,与上述两种方式不同,这种方式不要求映射文件名和接口名一致。这里是通过命名空间(namespace)和mapper接口对应的,命名空间要与接口的全限定名保持一致。
        4.<mapper url="file:///d:/CarMapper.xml" />是绝对路径加载映射文件的,而且 .xml 文件的名称并不需要和接口名称相同。通过命名空间指定和接口关系
        -->
        <mapper resource="CarMapper.xml"/>
    </mappers>
</configuration>

另外一个

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="asdsds">
    <insert id="insertCar">
        insert into t_car(id,car_num,brand,guide_price,produce_time,car_type)
        values(null,#{carNum},#{brand},#{guidePrice},#{produceTime},#{carType})
    </insert>


</mapper>

/**
 * @author hrui
 * @date 2023/5/15 0:40
 */
public class ParseXMLByDom4jTest {

    @Test
    public void testParseMyBatisConfigXML() throws DocumentException {
        //创建SAXReader对象
        SAXReader saxReader=new SAXReader();
        //获取输入流
        InputStream in=ClassLoader.getSystemClassLoader().getResourceAsStream("mybatisConfig.xml");
        //读XML,返回document对象.document对象是文档对象,代表整个XML文件
        //可以用同一个saxReader读不同输入流获取Document
        Document document=saxReader.read(in);
        //Document document2 = saxReader.read(Thread.currentThread().getContextClassLoader().getResourceAsStream("mybatisConfig.xml"));
        System.out.println(document);
        //System.out.println(document2);

        //获取文档当中的跟标签
        Element rootElement = document.getRootElement();
        String name = rootElement.getName();
        System.out.println(name);

    }
}

 

 现在我们一个个去获取,比如现在我需要获取的是

这样就可以拿到属性值了

public class ParseXMLByDom4jTest {

    @Test
    public void testParseMyBatisConfigXML() throws DocumentException {
        //创建SAXReader对象
        SAXReader saxReader=new SAXReader();
        //获取输入流
        InputStream in=ClassLoader.getSystemClassLoader().getResourceAsStream("mybatisConfig.xml");
        //读XML,返回document对象.document对象是文档对象,代表整个XML文件
        //可以用同一个saxReader读不同输入流获取Document
        Document document=saxReader.read(in);
        //Document document2 = saxReader.read(Thread.currentThread().getContextClassLoader().getResourceAsStream("mybatisConfig.xml"));
        System.out.println(document);
        //System.out.println(document2);

        //获取文档当中的跟标签
        Element rootElement = document.getRootElement();
        String name = rootElement.getName();
        System.out.println(name);

        //获取enviroments标签中 default默认的环境id
        //以下的xpath代表了:从根下开始找configuration标签,然后找configuration标签下的子标签environments(注意:需要有层级关系)
        String xpath="/configuration/environments";//xpath是做标签路径匹配的.能够让我们快速定位XML文件中的元素
        Node node = document.selectSingleNode(xpath);
        System.out.println(node);
        //强转成Element
        Element e=(Element)node;
        System.out.println(e.attributeValue("default"));
    }
}

 

 

 现在要做的就是获取环境,虽然我的配置文件里就一个环境,这里只为演示和了解Mybatis作者读取.XML时的思路

我们需要获取环境id为development的环境

下面一步一步获取各个节点和各个属性

public class ParseXMLByDom4jTest {

    @Test
    public void testParseMyBatisConfigXML() throws DocumentException {
        //创建SAXReader对象
        SAXReader saxReader=new SAXReader();
        //获取输入流
        InputStream in=ClassLoader.getSystemClassLoader().getResourceAsStream("mybatisConfig.xml");
        //读XML,返回document对象.document对象是文档对象,代表整个XML文件
        //可以用同一个saxReader读不同输入流获取Document
        Document document=saxReader.read(in);
        //Document document2 = saxReader.read(Thread.currentThread().getContextClassLoader().getResourceAsStream("mybatisConfig.xml"));
        System.out.println(document);
        //System.out.println(document2);

        //获取文档当中的跟标签
        Element rootElement = document.getRootElement();
        String name = rootElement.getName();
        System.out.println(name);

        //获取enviroments标签中 default默认的环境id
        //以下的xpath代表了:从根下开始找configuration标签,然后找configuration标签下的子标签environments(注意:需要有层级关系)
        String xpath="/configuration/environments";//xpath是做标签路径匹配的.能够让我们快速定位XML文件中的元素
        Node node = document.selectSingleNode(xpath);
        System.out.println(node);
        //强转成Element
        Element e=(Element)node;
        System.out.println(e.attributeValue("default"));
        //获取具体的环境environment,并且id是development的环境  xpath的语法[@属性名='属性值']
        xpath="/configuration/environments/environment[@id='development']";

        Element environment=(Element)document.selectSingleNode(xpath);
        System.out.println(environment);

        //获取指定环境environment节点下的transactionManager节点(Element的element()方法用来获取孩子节点)
        Element transactionManager = environment.element("transactionManager");
        //获取transactionManager中的type属性
        String type = transactionManager.attributeValue("type");
        System.out.println(type);//事务管理器的类型
        //获取DataSource节点
        Element dataSource = environment.element("dataSource");
        //获取DataSource节点 的type
        String dataSourceType = dataSource.attributeValue("type");
        System.out.println("dataSource的type属性值:"+dataSourceType);
        //获取dataSource下所有property节点
        List<Element> elements = dataSource.elements();
        //遍历
        elements.forEach(property->{
            String name1 = property.attributeValue("name");
            String value1 = property.attributeValue("value");
            System.out.println(name1+":"+value1);
        });

    }
}

 

下面解析mappers

public class ParseXMLByDom4jTest {

    @Test
    public void testParseMyBatisConfigXML() throws DocumentException {
        //创建SAXReader对象
        SAXReader saxReader=new SAXReader();
        //获取输入流
        InputStream in=ClassLoader.getSystemClassLoader().getResourceAsStream("mybatisConfig.xml");
        //读XML,返回document对象.document对象是文档对象,代表整个XML文件
        //可以用同一个saxReader读不同输入流获取Document
        Document document=saxReader.read(in);
        //Document document2 = saxReader.read(Thread.currentThread().getContextClassLoader().getResourceAsStream("mybatisConfig.xml"));
        System.out.println(document);
        //System.out.println(document2);

        //获取文档当中的跟标签
        Element rootElement = document.getRootElement();
        String name = rootElement.getName();
        System.out.println(name);

        //获取enviroments标签中 default默认的环境id
        //以下的xpath代表了:从根下开始找configuration标签,然后找configuration标签下的子标签environments(注意:需要有层级关系)
        String xpath="/configuration/environments";//xpath是做标签路径匹配的.能够让我们快速定位XML文件中的元素
        Node node = document.selectSingleNode(xpath);
        System.out.println(node);
        //强转成Element
        Element e=(Element)node;
        System.out.println(e.attributeValue("default"));
        //获取具体的环境environment,并且id是development的环境  xpath的语法[@属性名='属性值']
        xpath="/configuration/environments/environment[@id='development']";

        Element environment=(Element)document.selectSingleNode(xpath);
        System.out.println(environment);

        //获取指定环境environment节点下的transactionManager节点(Element的element()方法用来获取孩子节点)
        Element transactionManager = environment.element("transactionManager");
        //获取transactionManager中的type属性
        String type = transactionManager.attributeValue("type");
        System.out.println(type);//事务管理器的类型
        //获取DataSource节点
        Element dataSource = environment.element("dataSource");
        //获取DataSource节点 的type
        String dataSourceType = dataSource.attributeValue("type");
        System.out.println("dataSource的type属性值:"+dataSourceType);
        //获取dataSource下所有property节点
        List<Element> elements = dataSource.elements();
        //遍历
        elements.forEach(property->{
            String name1 = property.attributeValue("name");
            String value1 = property.attributeValue("value");
            System.out.println(name1+":"+value1);
        });

        //获取所有mapper标签
        xpath="//mapper";//不想从跟下开始获取,你想从任意位置开始,获取所有的某个标签,xpath该这样写  //开始
        List<Node> mappers = document.selectNodes(xpath);
        mappers.forEach(mapper->{
            //将Node强转成Element
            Element e1=(Element)mapper;
            String resource = e1.attributeValue("resource");
            System.out.println("resource:"+resource);
        });

    }
}

下面另写个方法解析.XML SQL映射文件

 

 @Test
    public void testParseSqlMapperXML() throws DocumentException {
        //创建SAXReader对象
        SAXReader saxReader=new SAXReader();
        //获取输入流
        InputStream in=ClassLoader.getSystemClassLoader().getResourceAsStream("CarMapper.xml");
        Document document=saxReader.read(in);

        //开始解析
        //获取namespace
        //Element rootElement = document.getRootElement();//这样也可以获取
        String xpath="/mapper";
        Element rootElement = (Element)document.selectSingleNode(xpath);
        System.out.println(rootElement);
        String namespace = rootElement.attributeValue("namespace");
        System.out.println(namespace);

        //上面已经获取了命名空间
        //下面获取mapper节点下所有的子节点
        List<Element> elements = rootElement.elements();
        elements.forEach(element -> {
            //获取sqlid
            String id = element.attributeValue("id");
            System.out.println(id);
            //获取resultType 没有该属性输出就是null
            String resultType = element.attributeValue("resultType");
            System.out.println(resultType);
            //看是insert 还是delete update  select
            String name = element.getName();
            System.out.println(name);
            //获取标签中的sql
            String textTrim = element.getTextTrim();
            System.out.println(textTrim);
        });
    }

这样该拿的都拿到了

现在得到的SQL是

insert into t_car(id,car_num,brand,guide_price,produce_time,car_type) values(null,#{carNum},#{brand},#{guidePrice},#{produceTime},#{carType})

Myabtis封装了JDBC,因此以后执行语句肯定会变成

insert into t_car(id,car_num,brand,guide_price,produce_time,car_type) values(null,?,?,?,?,?)

@Test
    public void testParseSqlMapperXML() throws DocumentException {
        //创建SAXReader对象
        SAXReader saxReader=new SAXReader();
        //获取输入流
        InputStream in=ClassLoader.getSystemClassLoader().getResourceAsStream("CarMapper.xml");
        Document document=saxReader.read(in);

        //开始解析
        //获取namespace
        //Element rootElement = document.getRootElement();//这样也可以获取
        String xpath="/mapper";
        Element rootElement = (Element)document.selectSingleNode(xpath);
        System.out.println(rootElement);
        String namespace = rootElement.attributeValue("namespace");
        System.out.println(namespace);

        //上面已经获取了命名空间
        //下面获取mapper节点下所有的子节点
        List<Element> elements = rootElement.elements();
        elements.forEach(element -> {
            //获取sqlid
            String id = element.attributeValue("id");
            System.out.println(id);
            //获取resultType 没有该属性输出就是null
            String resultType = element.attributeValue("resultType");
            System.out.println(resultType);
            //看是insert 还是delete update  select
            String name = element.getName();
            System.out.println(name);
            //获取标签中的sql
            String textTrim = element.getTextTrim();
            System.out.println(textTrim);
            //insert into t_car(id,car_num,brand,guide_price,produce_time,car_type) values(null,?,?,?,?,?)将SQL转换
            String s = textTrim.replaceAll("#\\{[0-9A-Za-z_$]*}", "?");//用正则将#{xxx}转成?
            System.out.println(s);
        });
    }

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/526417.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【C++】| 04——STL | 容器_vector

系列文章目录 【C】| 01——泛型编程 | 模板 【C】| 02——STL | 初识 【C】| 03——STL | 迭代器 【C】| 04——STL | 容器_vector 文章目录 1. vector容器2. vector库2.1 迭代器相关函数2.1 ww 1. vector容器 vector 与 动态数组 相似&#xff0c;可以自动调节自身大小。元素…

基于SpringBoot的美容院管理系统

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SpringBoot 前端&#xff1a;Vue 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#xff1a;是 目录 一、项目简介 二、系…

Windows10中英文切换按钮消失?一招解决

目录 问题场景&#xff1a; 问题描述 原因分析&#xff1a; 解决方案&#xff1a; 1. 打开设置&#xff0c;选择时间和语言 2. 进入日期时间设置 3. 进入高级键盘设置 4. 勾选这个勾选框&#xff0c;问题解决 问题场景&#xff1a; 博主玩道德与法治V在线模式时&#…

BGP防环,路由反射器,BGP联盟

数据的出口是路由的入口 ospf内部&#xff1a;10 ospf外部&#xff1a;150 静态路由&#xff1a;60 RIP&#xff1a;100 BGP&#xff1a;255 当下一跳是0.0.0.0 表示的是自己 display bgp peer //查看bgp邻居表 display bgp routing-table //查看bgp数据库 display i…

WPF MaterialDesign 初学项目实战(3)动态侧边栏

其他文章 WPF MaterialDesign 初学项目实战&#xff08;0&#xff09;:github 项目Demo运行 WPF MaterialDesign 初学项目实战&#xff08;1&#xff09;首页搭建 WPF MaterialDesign 初学项目实战&#xff08;2&#xff09;首页导航栏样式 创建侧边栏实体类 新建MenuBar文件…

Python动物图像分割API简单调用实例演示,阿里达摩院视觉智能开放平台使用步骤

阿里云视觉智能开放平台 - 动物分割 效果图演示平台入口创建获取密钥本地图片转 URL 与密钥测试代码调用演示语义分割知识拓展阿里云达摩院智能视觉开放平台 效果图演示 调用本地图片处理后可以直接保存到本地&#xff0c;右边就是分割好的效果图&#xff0c;可以看到分割的效…

基于卷积的图像分类识别(五):ResNet ResNeXt

系列文章目录 本专栏介绍基于深度学习进行图像识别的经典和前沿模型&#xff0c;将持续更新&#xff0c;包括不仅限于&#xff1a;AlexNet&#xff0c; ZFNet&#xff0c;VGG&#xff0c;GoogLeNet&#xff0c;ResNet&#xff0c;DenseNet&#xff0c;SENet&#xff0c;MobileN…

C语言实现扫雷

总有一天你要一个人在暗夜中&#xff0c;向那座桥走过去 目录 一、文件及其对应代码 1.test.c 2.game.c 3.game.h 二、数组创建解析 1.创建两个数组的原因 2.预设数组较大的原因 三、计算周围雷的个数 四、向外扩展并延伸判断 扫雷游戏&#xff0c;相信大家都玩过&am…

【c++】图解类和对象(上)

类和对象&#xff08;上&#xff09; 文章目录 类和对象&#xff08;上&#xff09;一、面向过程和面向对象初步认识二、类的引入三、类的定义四、类的访问限定符及封装1.访问限定符2.封装 五、类的作用域六、类的实例化七、类对象模型八、this指针总结 一、面向过程和面向对象…

Mysql中select语句的执行流程?

Mysql中select语句的执行流程&#xff1f; 答&#xff1a; SELECT 语句的执行过程为&#xff1a;连接、查询缓存、a词法分析&#xff0c;语法分析&#xff0c;语义分析&#xff0c;构造执行树&#xff0c;生成执行计划、执行器执行计划&#xff0c;下面开始梳理一次完整的查询…

【MySQL】视图,事务、隔离级别

视图--虚表&#xff0c;不在数据库中存放数据&#xff0c;数据源于基本表。 为什么要使用视图 简化复杂的sql操作&#xff0c;在编写查询后&#xff0c;可以方便的重用它而不必知道它的查询细节。重复使用该sql语句。使用表的组成部分而不是整个表。保护数据&#xff0c;可以给…

vscode编译的时候:未定义标识符 thread

vscode编译的时候&#xff1a;未定义标识符 thread thread’ was not declared in this scope" 未定义标识符 thread 原因 MinGW GCC当前仍缺少标准C 11线程类的实现。 对于跨平台线程实现&#xff0c;GCC标准库依赖于gthreads / pthreads库。如果该库不可用&#xf…

手搓GPT系列之 - 通过理解LSTM的反向传播过程,理解LSTM解决梯度消失的原理 - 逐条解释LSTM创始论文全部推导公式,配超多图帮助理解(上篇)

1. 前言 说起RNN和LSTM&#xff0c;就绕不过Sepp Hochreiter 1997年的开山大作 Long Short-term Memory。奈何这篇文章写的实在是太劝退&#xff0c;整篇论文就2张图&#xff0c;网上很多介绍LSTM的文章都对这个模型反向传播的部分避重就轻&#xff0c;更少见&#xff08;反正…

2023/5/14学习总结

这道题我们可以看到数据范围很小 &#xff0c;所以可以使用暴力枚举&#xff0c;将所有可以组成长方形的长宽全遍历一遍&#xff0c;同时要满足这个长方形里没有障碍物的条件&#xff0c;取得周长最大值 #include<bits/stdc.h> using namespace std; typedef long long …

JavaSE基础(六)—— 面向对象、封装、对象内存图、成员变量和局部变量区别

目录 一、面向对象对象介绍 1. 面向对象的重点学习什么 二、设计对象并使用 1. 设计类&#xff0c;创建对象并使用 1.1 如何得到对象 1.2 如何使用对象 2. 定义类的几个补充注意事项 2.1 对象的成员变量的默认值规则 三、对象内存图 1. 多个对象内存图 2. 两个变量指…

Springboot +Flowable,流程表单应用之静态表单

一.简介 整体上来说&#xff0c;我们可以将Flowable 的表单分为三种不同的类型&#xff1a; 动态表单 这种表单定义方式我们可以配置表单中每一个字段的可读性、可写性、是否必填等信息&#xff0c;不过不能定义完整的表单页面。外置表单 外置表单我们只需要定义一下表单的 k…

生命周期、数据共享、ref引用、购物车案例

生命周期&数据共享 1.组件的生命周期2.组件之间的数据共享3.ref 引用4.购物车案例 1.组件的生命周期 生命周期 & 生命周期函数 生命周期&#xff08;Life Cycle&#xff09;是指一个组件从创建 -> 运行 -> 销毁的整个阶段&#xff0c;强调的是一个时间段。 生命…

chatGPT提问,BGP内容

ChatGPT提问&#xff1a;提问框架 背景角色任务要求 动态路由&#xff1a;内部网关协议&#xff1a;如RIP ISIS OSPF 在同一个公司内部运行的路由协议 外部网关协议&#xff1a;如 BGP 在不同公司之间运行的路由协议 AS&#xff1a;自治系统 每个自治系统都有唯一的…

动态组件、插槽、自定义指令、Eslint和prettierrc配置、axios全局挂载

动态组件、插槽、自定义指令、Eslint和prettierrc配置、axios全局挂载 动态组件插槽体验插槽的基础用法作用域插槽 自定义指令Eslint和prettierrc配置prettierrc axios全局挂载 动态组件 动态组件指的是动态切换组件的显示与隐藏。 如何实现动态组件渲染 vue 提供了一个内置的…

Visual Studio 2022 CMake+MinGW+GDB 调试目标程序

前段时间笔者在使用MinGW编译了QtCreator后&#xff0c;想要进行调试。最开始使用VSCode进行调试&#xff0c;可是可以调试&#xff0c;但是发现调试过程中反应比较慢&#xff0c;毕竟QtCreator整个源代码工程还是非常大的&#xff0c;VSCode是由JS语言编写&#xff0c;执行效率…