美文网首页
数据库技术六:XML

数据库技术六:XML

作者: YMeng_Zhang | 来源:发表于2021-09-02 13:04 被阅读0次

    XML基本介绍

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

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

    XML的作用

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

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

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

    XML的语法

    XML 文档声明格式

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

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

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

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

    元素

    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. 一个元素可以有 0 ~ N 个属性,但一个元素中不能出现同名属性。
    4. 属性名不能使用空格、冒号等特殊字符,且必须以字母开头。
    <bean id="1" class="x"></bean>
    

    注释

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

    使用 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>
    

    XML约束

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

    常见的 XML 约束:DTD,Schema。

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

    • 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>
    
    • Schema约束

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

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

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

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

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

    创建 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>
    

    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>
    

    XML解析

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

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

    XML 解析方式

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

    • 优点:元素与元素之间保留结构关系,故可以进行增删改查操作。可以读取以及修改DOM 树任何部分。
    • 缺点:XML 文档过大,可能出现内存溢出显现。

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

    • 优点:占用内存少且处理速度快,可以处理大文件。
    • 缺点:只能顺序访问读取,不能修改。需要建立自己的 XML 对象模型,增加了开发难度。

    XML 常见的解析

    JAXP:Sun 公司提供的解析器,支持 DOM 和 SAX 两种思想。
    DOM4J:一款非常优秀的解析器,Dom4j 是一个易用的、开源的库,用于 XML,XPath 和 XSLT。它应用于 Java 平台,采用了 Java 集合框架并完全支持 DOM,SAX 和 JAXP。
    Jsoup:Jsoup 是一款 Java 的 HTML 解析器,也可以解析 XML。
    PULL:Android 内置的 XML 解析方式,类似 SAX。

    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);
        }
    }
    

    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());
        }
    }
    
    

    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();
        }
    }
    

    相关文章

      网友评论

          本文标题:数据库技术六:XML

          本文链接:https://www.haomeiwen.com/subject/aldmiltx.html