数据库技术六:XML

目录

1. XML基本介绍

1.1 XML的作用

1.2 XML的语法

1.2.1 XML 文档声明格式

1.2.2 元素

1.2.3 属性

1.2.4 注释

1.2.5 使用 XML 描述数据

2. XML约束

2.1 DTD约束

2.2 Schema约束

3. XML解析

3.1 XML 解析方式

3.2 XML 常见的解析

3.3 Dom4j 的使用

3.4 XPath 方式读取 XML

4. JDBC 自定义 XML


1. XML基本介绍

XML -- Extensible Markup Language,即可扩展标记语言。

XML 特点:可扩展的,标签都是自定义的;语法十分严格。

1.1 XML的作用

存储数据:通常,我们在数据库中存储数据。不过,如果希望数据的可移植性更强,我们可以把数据存储 XML 文件中。

配置文件:更多是作为各种技术框架的配置文件使用。

在网络中传输:客户端可以使用 XML 格式向服务器端发送数据,服务器接对 XML 格式数据进行解析。

1.2 XML的语法

1.2.1 XML 文档声明格式

文档声明必须为结束且必须写在第一行。

versioin:指定 XML 文档版本,是必需属性,因为不会选择 1.1,只会选择 1.0。

encoding:指定当前文档的编码,是可选属性,默认值是 utf-8。

<?xml version="1.0" encoding="UTF-8"?>

1.2.2 元素

Element 元素:是 XML 文档中最重要的组成部分。

命名规则:

  1. 不能使用空格,不能使用冒号
  2. XML 标签名称区分大小写
  3. XML 必须有且只有一个根元素
  4. XML 必须有且只有一个根元素,它是所有其他元素的父元素,比如以下 users 就是根元素。
<?xml version="1.0" encoding="utf-8" ?>
<users>
</users>

普通元素的结构开始标签、元素体、结束标签组成。

<hello>大家好</hello>

元素体:元素体可以是元素,也可以是文本。

<hello>
    <a>您好</a>
</hello>

空元素:空元素只有开始标签,而没有结束标签,但元素必须自己闭合。

<close/>

1.2.3 属性

  1. 属性是元素的一部分,它必须出现在元素的开始标签中。
  2. 属性的定义格式:属性名 = "属性值",其中属性值必须使用单引或双引。
  3. 一个元素可以有 0 ~ N 个属性,但一个元素中不能出现同名属性。
  4. 属性名不能使用空格、冒号等特殊字符,且必须以字母开头。
<bean id="1" class="x"></bean>

1.2.4 注释

XML 的注释:
以 <!-- 开始,以 --> 结束
注释内容会被XML解析器忽略。

1.2.5 使用 XML 描述数据

<?xml version="1.0" encoding="UTF-8" ?>
<employees>
    <employee eid="2">
        <ename>林黛玉</ename>
        <age>20</age>
        <sex>女</sex>
        <salary>5000</salary>
        <empdate>2019-03-14</empdate>
    </employee>
    <employee eid="3">
        <ename>杜甫</ename>
        <age>40</age>
        <sex>男</sex>
        <salary>15000</salary>
        <empdate>2010-01-01</empdate>
    </employee>
</employees>

2. XML约束

在 XML 技术里,可以编写一个文档来约束一个 XML 文档的书写规范,这称之为 XML 约束。

常见的 XML 约束:DTD,Schema。

“用户程序员”阅读 XML 约束文档,编写 XML 文档;
软件框架编写 XML 约束文档,解析 XML 文档;
XML 约束文档规定了 XML 文档的书写规则。

2.1 DTD约束

DTD - Document Type Definition,文档类型定义,用来约束 XML 文档。规定 XML 文档中元素的名称,子元素的名称及顺序,元素的属性等。

通过框架提供的 DTD 约束文档,编写对应的 XML 文档。常见框架使用 DTD 约束有:Struts2、hibernate 等。

引入 DTD 文档到 XML 文档中有两种方式:

  • 内部 DTD -- 将约束规则定义在 XML 文档中。
  • 外部 DTD -- 将约束的规则定义在外部的 DTD 文件中。

创建约束文件 student.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 #REQUIRED
student子元素中 有一个ID属性叫做 number,是必须填写的
ID: 唯一 值只能是字母或者下划线开头
-->

引入约束文档到 student.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE students SYSTEM "student.dtd">
<students>
    <student number="s1">
        <name>布莱尔</name>
        <age>22</age>
        <sex>男</sex>
    </student>
    <student number="s2">
        <name>张三</name>
        <age>55</age>
        <sex>男</sex>
    </student>
</students>

 2.2 Schema约束

Schema 是新的 XML 文档约束,比 DTD 强大很多,是 DTD 替代品。

Schema 本身也是 XML 文档,但 Schema 文档的扩展名为 xsd,而不是 xml。

Schema 功能更强大,内置多种简单和复杂的数据类型。

Schema 支持命名空间(一个 XML 中可以引入多个约束文档)。

命名空间:指的是一个环境,所用的标签来自于哪个环境定义的。

1. 创建 student.xsd
xmlns -- 表示此文档默认的命名空间是什么

xmlns:xsd -- 表示数据类型等定义的来源

targetNamespace -- 表示文档中要定义的元素来自哪个命名空间

elementFormDefault -- 表示要求 XML 文件的每一个元素都要有命名空间指定

<?xml version="1.0"?>
<xsd:schema xmlns="http://www.xxx.com/xml"
            xmlns:xsd="http://www.w3.org/2001/XMLSchema"
            targetNamespace="http://www.xxx.com/xml" 
            elementFormDefault="qualified">
    <xsd:element name="students" type="studentsType"/>
    <xsd:complexType name="studentsType">
        <xsd:sequence>
            <xsd:element name="student" type="studentType" minOccurs="0" 
                         maxOccurs="unbounded"/>
        </xsd:sequence>
    </xsd:complexType>
    <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>
        <xsd:attribute name="number" type="numberType" use="required"/>
    </xsd:complexType>
    <xsd:simpleType name="sexType">
        <xsd:restriction base="xsd:string">
            <xsd:enumeration value="male"/>
            <xsd:enumeration value="female"/>
        </xsd:restriction>
    </xsd:simpleType>
    <xsd:simpleType name="ageType">
        <xsd:restriction base="xsd:integer">
            <xsd:minInclusive value="0"/>
            <xsd:maxInclusive value="200"/>
        </xsd:restriction>
    </xsd:simpleType>
    <xsd:simpleType name="numberType">
        <xsd:restriction base="xsd:string">
            <xsd:pattern value="xxx_\d{4}"/>
        </xsd:restriction>
    </xsd:simpleType>
</xsd:schema>

2. XML 引入 Schema 约束
首先,查看 Schema 文档,找到根元素,在 student.xml 中写出来。

使用 xmlns 指令来声明根元素来自哪个命名空间。

在 xmlns:xsi 引入 W3C 的标准命名空间,复制即可。

使用 schemaLocation 来指定引入的命名空间跟哪个 XSD 文件对应,有两个取值:第一个为命名空间,第二个为 XSD 文件的路径。

<?xml version="1.0" encoding="UTF-8" ?>
<students xmlns="http://www.xxx.com/xml"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://www.xxx.com/xml student.xsd">
    <student number="xxx_1234">
        <name>张小红</name>
        <age>25</age>
        <sex>female</sex>
    </student>
    <student number="xxx_0000">
        <name>李大兵</name>
        <age>20</age>
        <sex>male</sex>
    </student>
</students>

3. XML解析

当将数据存储在 XML 后,希望通过程序获得 XML 的内容。如果使用 Java 的 IO 流是可以完成的,不过需要非常繁琐的操作,且开发中会遇到不同问题(只读、读写)。所以,为了方便了开发人员操作 XML,需要给不同问题提供不同的解析方式及对应的解析器。

解析器:就是根据不同的解析方式提供的具体实现。有的解析器操作过于繁琐,为了方便开发人员,有提供易于操作的解析开发包。

3.1 XML 解析方式

DOM -- Document Object Model:属于文档驱动。要求解析器把整个 XML 文档装载到内存,并解析成一个 Document 对象并建立 DOM 树,生成 DOM 树上的每个 Node 对象。

-- 优点:元素与元素之间保留结构关系,故可以进行增删改查操作。可以读取以及修改DOM 树任何部分。

-- 缺点:XML 文档过大,可能出现内存溢出显现。

SAX -- Simple API for XML:属于事件驱动,是一种速度更快,更有效的方法。它逐行扫描文档,一边扫描一边解析。并以事件驱动的方式进行具体解析,每执行一行,都将触发对应的事件。

-- 优点:占用内存少且处理速度快,可以处理大文件。

-- 缺点:只能顺序访问读取,不能修改。需要建立自己的 XML 对象模型,增加了开发难度。

3.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.3 Dom4j 的使用

首先导入 dom4j JAR 包。

使用核心类 SaxReader 加载 XML 文档获得 Document,通过 Document 对象获得文档的根元素,然后就可以操作了。

SaxReader 对象:read(…) 加载执行 XML 文档

Document 对象:getRootElement() 获得根元素

Element 对象:

  • elements(…) 获得指定名称的所有子元素。可以不指定名称
  • element(…) 获得指定名称的第一个子元素。可以不指定名称
  • getName() 获得当前元素的元素名
  • attributeValue(…) 获得指定属性名的属性值
  • elementText(…) 获得指定名称子元素的文本值
  • getText() 获得当前元素的文本内容

1. 使用 schema 约束编写 user.xsd

<?xml version="1.0" encoding="UTF-8" ?>
<xsd:schema xmlns="http://www.xxx.com/xml"
            xmlns:xsd="http://www.w3.org/2001/XMLSchema"
            targetNamespace="http://www.xxx.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>

2. 引入约束编写 user.xml

<?xml version="1.0" encoding="UTF-8" ?>
<users xmlns="http://www.xxx.com/xml"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.xxx.com/xml user.xsd">
    <user id="1">
        <name>张三</name>
        <age>20</age>
        <hobby>跑步</hobby>
    </user>
    <user id="2">
        <name>布莱尔</name>
        <age>10</age>
        <hobby>游泳</hobby>
    </user>
    <user id="3">
        <name>何小明</name>
        <age>40</age>
        <hobby>看书</hobby>
    </user>
</users>

3. 读取 XML

public class TestDOM4j {
    // 获取 XML 文件中的所有的元素名称(标签)
    @Test
    public void test1() throws DocumentException {
        // 获取 XML 解析对象
        SAXReader reader = new SAXReader();
        // 解析 XML 获取文档对象 document
        Document document = reader.read("user.xml");
        // 获取根元素
        Element rootElement = document.getRootElement();
        // 获取根元素名称
        System.out.println(rootElement.getName());
        // 获取根元素下的标签
        List<Element> elements = rootElement.elements();
        for (Element element : elements) {
            System.out.println("根标签下的子节点: " + element.getName());
            List<Element> eList = element.elements();
            for (Element e : eList) {
                System.out.println("user 标签下的子节点" + e.getName());
            }
            break;
        }
    }

    /**
     * 获取具体的节点内容
     */
    @Test
    public void test2() throws DocumentException {
        // 创建 XML 文档解析对象
        SAXReader sr = new SAXReader();
        // 读取 XML 获取到 document 对象
        Document document = sr.read("src\\user.xml");
        // 获取根节点
        Element rootElement = document.getRootElement();
        // 得到当前节点的所有子节点
        List<Element> elements = rootElement.elements();
        // 获取第一个子节点
        Element user = elements.get(0);
        // 获取所有信息
        String id = user.attributeValue("id");
        String name = user.elementText("name");
        String age = user.elementText("age");
        // 使用 getText 获取当前元素的文本内容
        String hobby = user.element("hobby").getText();
        System.out.println(id+" "+name+" "+age+" "+hobby);
    }
}

3.4 XPath 方式读取 XML

XPath 是一门在 XML 文档中查找信息的语言,可以是使用 XPath 查找 XML 中的内容。

由于 DOM4J 在解析 XML 时只能一层一层解析,所以当 XML 文件层数过多时使用会很不方便,结合 XPath 就可以直接获取到某个元素。

基于已经导入的 DOM4J 的 JAR 包,需要额外导入 jaxen JAR 包。

XPath 基本语法介绍

使用 Dom4j 支持 XPath 的操作的几种主要形式:

  • /AAA/DDD/BBB 选择 AAA 的子元素 DDD 的所有子元素
  • //BBB 选择所有 BBB 元素
  • //* 选择所有元素
  • BBB[1] 选择 BBB 第一个子元素, BBB[last()] 表示选择 BBB 最后一个子元素
  • //BBB[@id] 选择有 id 属性的 BBB 元素
  • //BBB[@id='b1'] 选择含有属性 id 且其值为 'b1' 的 BBB 元素

API 介绍:

selectSingleNode(query): 查找和 XPath 查询匹配的一个节点,参数是 XPath 查询串。

selectNodes(query) :得到的是 XML 根节点下的所有满足 XPath 的节点,参数是 XPath 查询串。

Node :节点对象。

XPath 读取 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>
/*
 * 使用 selectSingleNode 方法查询指定节点中的内容
 **/
@Test
public void test1() throws DocumentException {
    // 创建解析器对象
    SAXReader sr = new SAXReader();
    // 获取文档对象
    Document document = sr.read("book.xml");
    // 调用 selectSingleNode() 方法获取 name 节点对象
    Node node1 = document.selectSingleNode("/bookstore/book/name");
    System.out.println("节点: " + node1.getName());
    System.out.println("书名: " + node1.getText());
    // 获取第二本书的名称
    Node node2 = document.selectSingleNode("/bookstore/book[2]/name");
    System.out.println("第二本书的书名为: " + node2.getText());
}
/*
 * 使用 selectSingleNode 方法获取属性值或者属性值对应的节点
 **/
@Test
public void test2() throws DocumentException {
    // 创建解析器对象
    SAXReader sr = new SAXReader();
    // 获取文档对象
    Document document = sr.read("book.xml");
    // 获取第一个 book 节点的 id 属性的值
    Node node1 = document.selectSingleNode("/bookstore/book/attribute::id");
    System.out.println("第一个 book 的 id 值为: " + node1.getText());
    // 获取最后一个 book 节点的 id 属性的值
    Node node2 = document.selectSingleNode("/bookstore/book[last()]/attribute::id");
    System.out.println("最后一个 book 节点的 id 值为: " + node2.getText());
    // 获取 id 属性值为 book2 的书名
    Node node3 = document.selectSingleNode("/bookstore/book[@id='book2']");
    String name = node3.selectSingleNode("name").getText();
    System.out.println("id 为 book2 的书名是: " + name);
}
/*
 * 使用 selectNodes() 方法获取对应名称的所有节点
 **/
@Test
public void test3() throws DocumentException {
    // 创建解析器对象
    SAXReader sr = new SAXReader();
    // 获取文档对象
    Document document = sr.read("book.xml");
    // 打印获取所有节点
    List<Node> list = document.selectNodes("//*");
    for (Node node : list) {
        System.out.println("节点名: " + node.getName());
    }
    // 获取所有的书名
    List<Node> names = document.selectNodes("//name");
    for (Node name : names) {
        System.out.println(name.getText());
    }
    // 获取指定 id 值为 book1 的节点的所有内容
    List<Node> book1 = document.selectNodes("/bookstore/book[@id='book1']//*");
    for (Node node : book1) {
        System.out.println(node.getName() + " = " + node.getText());
    }
}


4. JDBC 自定义 XML

定义 XML 配置文件

创建自定义 XML 文件 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/db5?characterEncoding=UTF-8</property>
    <property name="user">root</property>
    <property name="password">root</property>
</jdbc>

使用 XPath 编写工具类

public class JDBCUtils {
    // 定义字符串变量, 记录获取连接所需要的信息
    public static String DRIVERNAME;
    public static String URL;
    public static String USER;
    public static String PASSWORD;
    // 静态代码块
    static {
        try {
            // 使用 XPath 读取 XML 中的配置信息
            SAXReader sr = new SAXReader();
            Document document = sr.read("jdbc-config.xml");
            DRIVERNAME = document.selectSingleNode("/jdbc/property[@name='driverClass']").getText();
            URL = document.selectSingleNode("/jdbc/property[@name='jdbcUrl']").getText();
            USER = document.selectSingleNode("/jdbc/property[@name='user']").getText();
            PASSWORD = document.selectSingleNode("/jdbc/property[@name='password']").getText();
            // 注册驱动
            Class.forName(DRIVERNAME);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    // 获取连接的静态方法
    public static Connection getConnection(){
        try {
            // 获取连接对象
            Connection connection = DriverManager.getConnection(URL, USER, PASSWORD);
            // 返回连接对象
            return connection;
        } catch (SQLException e) {
            e.printStackTrace();
            return null;
        }
    }
}

测试工具类

// 获取所有员工的姓名
public static void main(String[] args) {
    try {
        // 获取连接
        Connection connection = JDBCUtils.getConnection();
        // 获取 statement 和执行 SQL
        Statement statement = connection.createStatement();
        String sql = "select * from employee";
        // 处理结果集
        ResultSet resultSet = statement.executeQuery(sql);
        while(resultSet.next()){
            String ename = resultSet.getString("ename");
            System.out.println(ename);
        }
    } catch (SQLException e) {
        e.printStackTrace();
    }
}
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值