暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

数据库技术:XML

Renda 2021-04-27
367


Introduction to XML

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

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

Functions of XML

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

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

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


XML Syntax

XML 文档声明格式

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

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

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

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

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

命名规则:

  1. 不能使用空格,不能使用冒号

  2. XML 标签名称区分大小写

  3. XML 必须有且只有一个根元素

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 Constraints

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

常见的 XML 约束:DTD,Schema。

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

DTD Constraint

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 Constraint

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 Parser

当将数据存储在 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()
    获得当前元素的文本内容

使用 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>
引入约束编写 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>
读取 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();
  }
}




文章转载自Renda,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论