一、XML配置文件和properties配置文件的对比
二、XML的基本语法
<?xml version="1.0" encoding="utf-8" ?>
<!-- xml文件的文档声明,需要注意的是:必须写在文件的开头位置,必须是第一行,注释都不可以放在第一行 -->
<!-- XML文件中有且只有一个根元素users元素 -->
<users>
<!-- 元素标签的命名中不可以包含 空格 和一些特殊符号.如 : -->
<!--
1.元素标签中可以设置该元素的属性和属性值,属性值使用单引号 / 双引号包裹
2.元素的属性可以有多个
3.元素的属性只可以写在元素的开始标签内部
-->
<user id="1" vip="true">
<!-- user元素体中可以是文本内容也可以是元素标签-->
内容
<name>zhangfei</name>
<age>18</age>
</user>
<user id="2">
内容
<name>guanyu</name>
<age>20</age>
</user>
<!-- 元素的命名是区分大小写的 -->
<USER>
<NAME></NAME>
<AGE></AGE>
</USER>
<!-- xml文件中也可以定义空元素标签 -->
<close/>
</users>
三、使用XML基本语法描述数据库中表的基本信息
<?xml version="1.0" encoding="UTF-8" ?>
<users>
<user id="1">
<userName>林黛玉</userName>
<password>123456</password>
</user>
<user id="2">
<userName>贾宝玉</userName>
<password>789456</password>
</user>
</users>
四、XML文件的约束
在实际开发中,XML文件的书写也不是任意的,需要我们遵守一定的规则。
1.自定义DTD约束并引入XML文件中
(1) 定义DTD约束文件
<!ELEMENT students (student+) >
<!ELEMENT student (name,age,sex)>
<!ELEMENT name (#PCDATA)>
<!ELEMENT age (#PCDATA)>
<!ELEMENT sex (#PCDATA)>
<!ATTLIST student number ID #REQUIRED>
<!--
ELEMENT 定义元素
students (student+): students 代表根元素
student+ : 根标签中 至少有一个 student子元素
student (name,age,sex) : student标签中可以 包含的子元素 按顺序出现
#PCDATA : 普通的文本内容
ATTLIST : 用来定义属性
student number ID : student标签中 有一个ID属性 叫做 number
#REQUIRED : number的属性必须填写
ID 表示number属性的值是 唯一的 不能重复 只能是字母或者下划线开头
-->
(2) 引入DTD约束文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE students SYSTEM "student.dtd">
<students>
<student number="s1">
<name>张飞</name>
<age>18</age>
<sex>1</sex>
</student>
<student number="s2">
<name>黄月英</name>
<age>18</age>
<sex>0</sex>
</student>
</students>
(2) 引入DTD约束文件的方式
- 内部dtd:将约束规则定义在xml文档中
- 外部dtd:将约束规则定义在外部的dtd文件中 。既可以引用本地的dtd文件,也可以引用网络上的dtd文件。
1.自定义schema约束并引入XML文件中
(1) 定义schema约束文件
<?xml version="1.0" encoding="UTF-8" ?>
<xsd:schema xmlns="http://www.xuguowen.com/xml"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.xuguowen.com/xml" elementFormDefault="qualified">
<!-- 根元素是 students,类型是studentsType -->
<xsd:element name="students" type="studentsType"/>
<!-- 类型是studentsType 根元素的子元素是 student 最小出现次数 0 最大出现次数不限制 -->
<xsd:complexType name="studentsType">
<xsd:sequence>
<xsd:element name="student" type="studentType" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
<!--
student元素的子元素是 name,age,sex。
name标签中内容的类型是string
age标签中内容的类型是 ageType
sex标签中内容的类型是 sexType
-->
<xsd:complexType name="studentType">
<xsd:sequence>
<xsd:element name="name" type="xsd:string"/>
<xsd:element name="age" type="ageType" />
<xsd:element name="sex" type="sexType" />
</xsd:sequence>
<!-- 属性number 的类型是 numberType required表示属性是必须要有的-->
<xsd:attribute name="number" type="numberType" use="required"/>
</xsd:complexType>
<!-- sex标签中内容的类型是string类型的,值可以是male、female-->
<xsd:simpleType name="sexType">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="male"/>
<xsd:enumeration value="female"/>
</xsd:restriction>
</xsd:simpleType>
<!-- age标签中内容的类型是integet类型的,值在0 - 200 之间 -->
<xsd:simpleType name="ageType">
<xsd:restriction base="xsd:integer">
<xsd:minInclusive value="0"/>
<xsd:maxInclusive value="200"/>
</xsd:restriction>
</xsd:simpleType>
<!-- 属性number的类型是string类型的,值是hehe_任意的4个数字-->
<xsd:simpleType name="numberType">
<xsd:restriction base="xsd:string">
<xsd:pattern value="hehe_\d{4}"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:schema>
(2) 引入xsd约束文件
<?xml version="1.0" encoding="UTF-8" ?><!--文档声明-->
<students
xmlns="http://www.xuguowen.com/xml"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.xuguowen.com/xml student.xsd"
>
<student number="hehe_1234">
<name>zhnagfei</name>
<age>28</age>
<sex>female</sex>
</student>
<student number="hehe_1234">
<name>关羽</name>
<age>200</age>
<sex>male</sex>
</student>
</students>
五、XML文件解析方式的介绍
1.解析概述
当将数据存储在XML后,我们就希望通过程序获得XML的内容。如果我们使用Java基础所学习的IO知识是可以完成的,不过你需要非常繁琐的操作才可以完成,且开发中会遇到不同问题(只读、读写)。
人们为不同问题提供不同的解析方式,并提交对应的解析器,方便开发人员操作XML。
2.XML解析方式
-
DOM:要求解析器把整个XML文档装载到内存,并解析成一个Document对象。
- 优点:元素与元素之间保留结构关系,故可以进行增删改查操作。
- 缺点:XML文档过大,可能出现内存溢出显现。
-
SAX:是一种速度更快,更有效的方法。它逐行扫描文档,一边扫描一边解析。并以事件驱动的方式进行具体解析,每执行一行,都将触发对应的事件。(了解)
- 优点:占用内存少 处理速度快,可以处理大文件
- 缺点:只能读,逐行后将释放资源。
2.常见的XML解析器
解析器:就是根据不同的解析方式提供的具体实现。有的解析器操作过于繁琐,为了方便开发人员,有提供易于操作的解析开发包。
- JAXP:sun公司提供的解析器,支持DOM和SAX两种思想
- DOM4J:一款非常优秀的解析器 , Dom4j是一个易用的、开源的库,用于XML,XPath和XSLT。它应用于Java平台,采用了Java集合框架并完全支持DOM,SAX和JAXP。
- Jsoup:jsoup 是一款Java 的HTML解析器 ,也可以解析XML
- PULL:Android内置的XML解析方式,类似SAX。
3.DOM4J API的介绍
(1)导入jar包
(2)常见 API介绍
- SaxReader对象
- read(…) 加载执行xml文档
- Document对象
- getRootElement() 获得根元素
- Element对象
- elements(…) 获得指定名称的所有子元素。可以不指定名称
- element(…) 获得指定名称的第一个子元素。可以不指定名称
- getName() 获得当前元素的元素名
- attributeValue(…) 获得指定属性名的属性值
- elementText(…) 获得指定名称子元素的文本值
- getText() 获得当前元素的文本内容
(3)准备工作
编写user.xsd schema约束
<?xml version="1.0" encoding="UTF-8" ?>
<xsd:schema xmlns="http://www.xuguowen.com/xml"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.xuguowen.com/xml"
elementFormDefault="qualified">
<xsd:element name="users" type="usersType"/>
<xsd:complexType name="usersType">
<xsd:sequence>
<xsd:element name="user" type="userType" minOccurs="0"
maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="userType">
<xsd:sequence>
<xsd:element name="name" type="xsd:string"/>
<xsd:element name="age" type="ageType" />
<xsd:element name="hobby" type="hobbyType" />
</xsd:sequence>
<xsd:attribute name="id" type="numberType" use="required"/>
</xsd:complexType>
<xsd:simpleType name="ageType">
<xsd:restriction base="xsd:integer">
<xsd:minInclusive value="0"/>
<xsd:maxInclusive value="100"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="hobbyType">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="抽烟"/>
<xsd:enumeration value="喝酒"/>
<xsd:enumeration value="烫头"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="numberType">
<xsd:restriction base="xsd:string">
<xsd:pattern value="\d"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:schema>
编写user.xml文件,引入user.xsd约束
<?xml version="1.0" encoding="UTF-8" ?>
<users
xmlns="http://www.xuguowen.com/xml"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.xuguowen.com/xml user.xsd"
>
<user id="001">
<name>张飞</name>
<age>18</age>
<hobby>二次元</hobby>
</user>
<user id="002">
<name>张百万</name>
<age>25</age>
<hobby>丝袜</hobby>
</user>
<user id="003">
<name>波比</name>
<age>30</age>
<hobby>JK</hobby>
</user>
</users>
(4)解析xml,获取xml文件中的信息
package cn.xuguowen.dom4j;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.junit.Test;
import java.util.List;
/**
* @author 徐国文
* @create 2021-09-09 9:58
* 测试:使用dom4j的解析方式解析user.xml文件
* 1.导入jar包
*/
public class TestDOM4j {
/**
* 测试获取xml文件中得根标签以及子标签
* @throws DocumentException
*/
@Test
public void test1() throws DocumentException {
// 1.创建核心对象SaxReader
SAXReader saxReader = new SAXReader();
// 2.调用read()方法读取指定的xml文件,获取document对象
Document document = saxReader.read("src\\cn\\xuguowen\\dom4j\\user.xml");
// 3.获取根标签对象
Element rootElement = document.getRootElement();
System.out.println("根标签的名称" + rootElement.getName()); // 根标签的名字 users
// 4.获取根标签下的子标签user
List<Element> elements = rootElement.elements();
for (Element element : elements) {
System.out.println("根标签下的子标签" + element.getName()); // user
// 获取user标签下的子标签
List<Element> elements1 = element.elements();
for (Element element1 : elements1) {
System.out.println("user标签下的子标签" + element1.getName());
}
break;
}
}
/**
* 获取标签中得属性和文本内容
*/
@Test
public void test2() throws DocumentException {
// 1.SAXReader核心对象
SAXReader saxReader = new SAXReader();
// 2.读取xml文件,获取document对象
Document document = saxReader.read("src\\cn\\xuguowen\\dom4j\\user.xml");
// 3.获取document树中得根标签对象
Element rootElement = document.getRootElement();
// 4.获取根标签下得所有子标签
List<Element> elements = rootElement.elements();
// 5.获取了所有子标签的集合之后:list集合,可以通过索引获取其中的元素
Element user = elements.get(0);
System.out.println("获取到了第一个子标签是:" + user.getName());
// 6.再去获取user标签中的子标签的内容
String name = user.elementText("name");
String age = user.elementText("age");
String hobby = user.element("hobby").getText();
// 7.获取user标签中的属性的值
String id = user.attributeValue("id");
System.out.println("name标签中的文本内容:" + name);
System.out.println("age标签中的文本内容:" + age);
System.out.println("hobby标签中的文本内容:" + hobby);
System.out.println("id属性的值是:" + id);
}
}
4.XPath API的介绍
XPath的优点:由于DOM4J在解析XML时只能一层一层解析,所以当XML文件层数过多时使用会很不方便,结合XPATH就可以直接获取到某个元素。
(1)XPath基本语法介绍
表格 | 说明 |
---|---|
/AAA/DDD/BBB | 表示一层一层的,AAA下面 DDD下面的BBB |
//BBB | 表示和这个名称相同,表示只要名称是BBB,都得到 |
//* | 所有元素 |
BBB[1] , BBB[last()] | 第一种表示第一个BBB元素, 第二种表示最后一个BBB元素 |
//BBB[@id] | 表示只要BBB元素上面有id属性,都得到 |
//BBB[@id=‘b1’] | 表示元素名称是BBB,在BBB上面有id属性,并且id的属性值是b1 |
(2)API介绍
- selectSingleNode(query): 查找和 XPath 查询匹配的一个节点。
参数是Xpath 查询串。 - selectNodes(query): 得到的是xml根节点下的所有满足 xpath 的节点;
参数是Xpath 查询串。 - Node: 节点对象
(3)XPath读取XML
数据准备xml文件
<?xml version="1.0" encoding="UTF-8" ?>
<bookstore>
<book id="book1">
<name>金瓶梅</name>
<author>金圣叹</author>
<price>99</price>
</book>
<book id="book2">
<name>红楼梦</name>
<author>曹雪芹</author>
<price>69</price>
</book>
<book id="book3">
<name>Java编程思想</name>
<author>埃克尔</author>
<price>59</price>
</book>
</bookstore>
代码实现
package cn.xuguowen.xpath;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;
import org.junit.Test;
import java.util.List;
/**
* @author 徐国文
* @create 2021-09-09 20:18
* 导入jar包
*/
public class TestXPath {
/**
* 使用selectSingleNode() 方法获取单个节点
*/
@Test
public void test1() throws DocumentException {
// 1.核心对象SAXReader
SAXReader saxReader = new SAXReader();
// 2.读取xml文档,获取document对象
Document document = saxReader.read("src\\cn\\xuguowen\\xpath\\book.xml");
// 3.selectSingleNode()方法获取单个节点:默认情况下是获取第一个节点
Node node1 = document.selectSingleNode("/bookstore/book/name");
System.out.println("获取到的节点是:" + node1.getName());
System.out.println("节点的文本内容:" + node1.getText()); // 金瓶梅
// 获取第二个节点book中name标签中的文本内容
Node node2 = document.selectSingleNode("/bookstore/book[2]/name");
System.out.println("第二个book节点中name标签的文本内容:" + node2.getText());
}
/**
* 通过节点获取属性值 和 通过属性值获取节点中的信息
*/
@Test
public void test2() throws DocumentException {
SAXReader saxReader = new SAXReader();
Document document = saxReader.read("src\\cn\\xuguowen\\xpath\\book.xml");
// 通过id属性获取第一个book节点中的属性值
Node node1 = document.selectSingleNode("/bookstore/book/attribute::id");
System.out.println("第一个book节点的id属性值是:" + node1.getText()); // book1
// 通过id属性获取最后一个book节点中的属性值
Node node2 = document.selectSingleNode("/bookstore/book[last()]/attribute::id");
System.out.println("最后一个book节点的id属性值是:" + node2.getText());// book3
// 通过id属性值获取节点信息:比如:通过id属性值为book2 获取所在的节点信息
Node node3 = document.selectSingleNode("/bookstore/book[@id='book2']");// 获取到了第二个book节点
System.out.println(node3.selectSingleNode("name").getText()); // 红楼梦
}
/**
* 测试selectNodes()方法
*/
@Test
public void test3() throws DocumentException {
SAXReader saxReader = new SAXReader();
Document document = saxReader.read("src\\cn\\xuguowen\\xpath\\book.xml");
// 1.获取所有的节点
List<Node> allNode = document.selectNodes("//*");
for (Node node : allNode) {
System.out.println("获取到的所有节点名称是:" + node.getName() + "\t");
}
System.out.println("==================");
// 2.获取所有的书名:书名都在name标签中
List<Node> allName = document.selectNodes("//name");
for (Node node : allName) {
System.out.println(node.getText());
}
System.out.println("======================");
// 3.获取id属性值为book2的节点的所有信息
List<Node> book2 = document.selectNodes("/bookstore/book[@id='book2']//*");
for (Node node : book2) {
System.out.println("节点名为:" + node.getName() + " 节点的内容:" + node.getText());
}
}
}
六、JDBC工具类自定义XML文件
1.编写jdbc-config.xml配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<jdbc>
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/day17?
characterEncoding=UTF-8</property>
<property name="user">root</property>
<property name="password">root</property>
</jdbc>
2.编写JDBC工具类
package cn.xuguowen.jdbc;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;
import org.junit.Test;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
/**
* @author 徐国文
* @create 2021-09-09 21:25
* 使用dom4j+XPath语法解析jdbcxml文件,获取数据库的连接
*/
public class JDBCUtils {
// 类变量保存解析xml文件获取的内容
public static String driverName;
public static String jdbcurl;
public static String user;
public static String password;
// 静态代码块加载xml文件,读取xml文件,给类变量设置值
static {
SAXReader saxReader = new SAXReader();
try {
Document document = saxReader.read("src\\cn\\xuguowen\\jdbc\\jdbc-config.xml");
// 1.获取驱动名称
Node driver = document.selectSingleNode("/jdbc/property[@name='driverClass']");
driverName = driver.getText();
// 2.获取url
Node url = document.selectSingleNode("/jdbc/property[@name='jdbcUrl']");
jdbcurl = url.getText();
// 3.获取用户名
Node mysqlUser = document.selectSingleNode("/jdbc/property[@name='user']");
user = mysqlUser.getText();
// 4.获取密码
Node pw = document.selectSingleNode("/jdbc/property[@name='password']");
password = pw.getText();
// 5.注册驱动
Class.forName(driverName);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 获取数据库的连接
* @return
*/
public static Connection getConnection() {
try {
Connection connection = DriverManager.getConnection(jdbcurl, user, password);
return connection;
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return null;
}
}
3.测试是否可以获取连接
package cn.xuguowen.jdbc;
import org.junit.Test;
import java.sql.Connection;
/**
* @author 徐国文
* @create 2021-09-09 21:38
*/
public class TestConnection {
@Test
public void test() {
Connection connection = JDBCUtils.getConnection();
System.out.println(connection);
}
}