xml文件归纳总结

本文介绍了XML文件的重要性,特别是在Java框架配置中的应用,并详细讲解了XML文件的基本结构和特点。通过示例展示了如何使用DOM4j解析XML,包括解析方法的优劣以及XPath的使用,最后给出了一个解析MyBatis配置文件的实际例子,从中提取数据库连接信息。
摘要由CSDN通过智能技术生成

为什么要学习xml文件的相关知识?

最近学习Java的过程中,遇到了很多xml后缀的配置文件,如web.xml, pom.xml, mybatis-config.xml等。绝大多数框架和软件使用的配置文件都是xml,这体现了xml应用的广泛性。这些框架既然使用了这些xml配置文件,那么难免需要解析它,对于我们开发者而言,学习如何解析xml文件有利于帮助我们理解框架的设计思想和使用。

本篇博客将要总结的内容

  1. 我会先总结一下xml文件的格式,了解它的大体结构以及如何使用
  2. 从xml文件格式来分析总结使用它有哪些好处,以及它的主要用途
  3. 如何利用Java语言去解析xml文件,解析的方法?方法的优劣?具体怎么使用
  4. 结合xml以及反射的技术来做一个示例程序

xml文件简介

xml的英文全称是extensible markup language, 它的大体格式在下方我分别展示了mybatis-config.xml和pom.xml中的部分内容。

<?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="mysql">
  	<environment id="mysql">
		<transactionManager type="JDBC"/>  	
  	</envrionment>
  </environments>
</configuration>

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.person</groupId>
    <artifactId>mybatis-crud002</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>
    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
            <scope>test</scope>
        </dependency>
    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
</project>

第一行 <?xml version="1.0" encoding="UTF-8" ?>
声明了这是一个xml格式的文件,它的版本号是1.0,字符编码是UTF-8,这没啥好说的,基本是固定格式
第二行,我们发现两个文件内容是不同的,第一个xml文件中,它的内容是

<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">

它表明了当前的xml文件的根标签应该是configuration,这与html文件的声明根标签是html类似, 下面的网址指向了一个dtd文件,dtd的全称是Document Type Definition,它的作用是规定了当前xml文件可以使用哪些标签,应该遵守哪些规范。
为什么要有这个规范要求呢?对于一个框架而言,它必须得规定其配置文件的格式,这样在运行时才能正确的解析。就像人与人之间交流需要先确定统一的语言。由于xml的标签可以自定义(这个在后面的特点分析中总结),那么这种规范就是必须的。
了解html的读者就会发现xml与它的第一个不同之处了,w3c已经规定了html中有哪些标签,正确的结构是怎么样的,你只有按照要求编写,浏览器才能正确解析。
当然dta文件一般是框架开发者才需要编写的东西,对于我们应用层的开发者而言,遵守框架的配置规范即可。

那么第二个文件为什么是下面这样呢?

<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
 ...
 </project>

xsi:schemaLocation同样是一个url地址,它指向的是一个xsd文件,xsd文件是dtd文件的升级,但它们的做一个是相同的,都是xml文件的规范,唯一值得我们开发者注意的是,它的url地址直接作为一个属性写在了根结点上,不需要声明根结点了。

上面是maven和mybatis的配置文件,那么我们自己怎么编写xml文件呢?

<?xml version="1.0" encoding="UTF-8" ?>
<school>
	<students>
		<student id="2201">
			<name>张三</name>
			<age>22</age>
		</student>
	</students>
	<teachers>
		<teacher id="6603">
			<name>罗翔</name>
			<age>42</age>
		</teacher>
	</teachers>
</school>

我们自定义了一个根标签,其中嵌套了students和teachers标签,students和teachers分别还可以嵌套子标签, 标签还可以自己的属性(如id)。我们发现它的语法和html几乎一样,事实上它们都是标记语言,自然写法一样。
我们发现,school, teacher, student这些标签都是我们自定义的,想取什么名字都可以, 这种嵌套的结构层次结构分明,一目了然。同时,还可以发现,我们并没有写dtd或者xsd文件,因为该xml文件仅仅是我们个人用来存储数据,而没有给别人使用,自然不需要定义规范。

xml文件的特点和用途

上面简单的展示了一下xml怎么写,它的大概结构是怎么样的。下面我根据网上一些资料以及自己的理解来总结一下xml文件的特点以及用途。

  1. xml可以自定义标签以及标签的属性,需要注意的是它对大小写敏感
  2. xml是一个高度结构化的语言,层次清晰
  3. xml是一个纯文本,这样与平台无关,每一台机器上xml文件都是一致的

上面是我觉得最主要的三个特点,由此也衍生出xml文件的用途

存储和传输数据

在上面的例子中,我们事实上保存一个student和teacher类型的数据,student分别包括name和age字段,teacher同样也具有name和age字段。这意味着如果我们的应用需要存储什么信息就可以用一个xml文件保存,可读性很强。
由于它是一个纯文本,可以跨平台,自然就可以作为数据传输的载体。浏览器中有个对象叫做XMLHttpRequest,它对应的技术叫做AJAX,全称是Asynchronous JavaScript and XML,可以揣测,在JSON流行之前,XML是前后端通信的主要数据格式。

用作配置文件

这个作用也是我学习XML的初衷,绝大多数的Java框架都是用XML文件作为配置文件。这是由于XML文件本身的灵活性决定的,标签自由配置使得配置项丰富灵活,高度结构化为解析带来了一定的便利。
这里插入一个额外的讨论,就是JSON和XML谁做配置文件更好的问题。JSON的格式简介,在解析上的速度绝对是快于XML文件的,但我个人觉得XML文件的可读性更好(个人观点,有些人觉得json可读性更好),之所以有这种感受,是因为在python中我接触了到一些深度学习算法采用json作为配置文件,看起来眼花缭乱。当然JSON的优势还是大于XML的,毕竟是后面出现的技术。

解析XML文件

四种方式

  1. DOM方法解析
  2. SAX方式解析
  3. JDom方法
  4. dom4j方法

xml与html在结构和语法上相同,自然而然可以通过DOM来解析,这是一种与平台无关的规范。核心思想就是将文件看作一个文档对象,每一个结点看作一个对象,一个文档对象有一个根结点,结点之间的关系用树的数据结构来描述。解析时DOM会在内存中构建一棵DOM树,这样的坏处是容易超内存,解析速度慢。

SAX方法也是与平台无关的,速度较于DOM也更快,但是不能修改结点。

JDom和dom4j都是基于Java语言的,但是dom4j更为强大,是四个中效率最高的。

dom4j解析XML文件

使用dom4j需要相应的jar包支持,我是用maven管理的项目,直接引入依赖即可,如果不会maven,可以从网上找到dom4j的jar包资源,配置到系统的环境变量CLASSPATH下也可以使用。

package person.example;
import org.dom4j.Document;
import org.dom4j.io.SAXReader;
import org.junit.Test;
import java.io.InputStream;

public class Dom4jTest {
    @Test
    public void testDom() throws Exception {
        InputStream is = Dom4jTest.class.getClassLoader().getResourceAsStream("school.xml");
        SAXReader saxReader = new SAXReader();
        Document document = saxReader.read(is);
        System.out.println(document);
    }
}

第一步, 获得一个输入流,这里为了代码具有更好的移植性,采用的是

InputStream is = Dom4jTest.class.getClassLoader().getResourceAsStream("school.xml");

这样从类的根路径下进行查找,而静态资源也是往往放到类的根路径下。

第二步,创建一个解析对象

SAXReader saxReader = new SAXReader();

第三步,将输入流传递到解析对象中,它会帮助我们解析流的内容,返回一个文档对象

Document document = saxReader.read(is);

通过document.getRootElement()我们可以获得当前文档的根结点, 返回的是Element类型,每一个结点都是Element类型

Element root = document.getRootElement()
List<Element> elements = root.elements();
elements.forEach(e -> System.out.println(e.getName()));

elements()用来返回当前结点下所有子结点, getName可以获得当前标签的名字

可是如果我们这样一层层的去找到需要的元素,在编码效率上未免太低了,所以dom4j提供了一种xpath的检索结点的方法

Node node = document.selectSingleNode("school/students/student")

这个方法通过传入一个路径的检索形式返回一个Node类型的结点,Node类型是Element类型的父类,有许多方法不能用,在使用时需要向下转型成Element

Element element = (Element) document.selectSingleNode("school/students/student");

注意要想转型成功,需要在pom.xml中引入jaxen这个依赖

<dependency>
            <groupId>jaxen</groupId>
            <artifactId>jaxen</artifactId>
            <version>1.2.0</version>
       </dependency>
System.out.println(element.getName());
System.out.println(element.attribute("id").getValue());

拿到结点以后可以获取其属性的值

xpath还有其它一些用法,如下

List<Element> students = root.selectNodes("students/student");
        students.forEach(e -> {
            System.out.println(e.getName());
        });

selectNodes可以返回指定结点类型的列表

List<Element> students = root.selectNodes("//name");
        students.forEach(e -> {
            System.out.println(e.getData());
        });

//name 前面的两个/ 表示忽略层级和位置,找到root结点下所有的name结点,通过getData的方法,可以拿到它包含的数据。

List<Element> students = root.selectNodes("//*[@id]");
        students.forEach(e -> {
            System.out.println(e.getName());
        });

*表示通配符,可以匹配任意结点 【@属性值】,表示拥有id的属性的任意标签

 List<Element> students = root.selectNodes("//*[@id='110']");

表示任意i包含id属性,且id="110"的标签

以上的匹配规则基本够用了,下面我们就开始利用这些知识来实践一下。

实践

<?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>
    <settings>
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/test_db?useSSL=false&amp;useUnicode=true&amp;characterEncoding=UTF-8"/>
                <property name="username" value="root"/>
                <property name="password" value="1234"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="carMapper.xml"/>
    </mappers>
</configuration>

下面我们尝试解析一下mybatis的配置文件,来一个简单的任务,找到dataSource下面的property标签,拿到它们的value值,连接数据库,之前,需要引入数据库的驱动依赖。

public void testBatis() throws Exception{
        InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream("mybatis-config.xml");
        SAXReader saxReader = new SAXReader();
        Document document = saxReader.read(is);
        List<Element> property = document.selectNodes("//dataSource/property");
        String url = "";
        String username = "";
        String driver = "";
        String password = "";
        for(Element p : property){
            String name = p.attributeValue("name");
            String value = p.attributeValue("value");
            if(name.equals("url")){
                url = value;
            }else if(name.equals("username")){
                username = value;
            }else if(name.equals("driver")){
                driver = value;
            }else if(name.equals("password")){
                password = value;
            }
        }
        Class.forName(driver);
        Connection connection = DriverManager.getConnection(url, username, password);
        System.out.println(connection);
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值