29 XML

81 阅读7分钟

1 XML基本介绍

XML是可扩展标记语言,特点是是可扩展的,标签都是自定义,且语法严格,XML主要用来存储数据、作为配置文件以及在网络中传输数据。

接下来介绍下XML的语法:

XML文档声明格式

文档声明必须以< ? xml开头,以?>结尾,并且文档声明必须写在第一行。具体语法格式如下:

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

元素

Element元素是X ML文档中重要的组成部分,且元素的命名规则是:

  • 不能使用空格,不能使用冒号
  • xml标签是区分大小写的
  • xml只有一个根元素

语法格式:

<?xml version="1.0" encoding="utf-8"?>
<users>
  <hello>
    大家好
  </hello>
  <hello>
    <a>你好</a>
  </hello>
  <close/>
</users>
<!--
上面users就是根元素,它是其它元素的父元素
hello就是普通元素,是由开始标签、元素体以及结束标签组成,其中元素体可以是文本,也可以是元素
close是空元素,只有开始标签,没有结束标签,且元素自己闭合
 -->

属性

<bean id="" class=""></bean>

属性是元素的一部分,他必须出现在元素的开始标签中,且属性定义格式是:属性名=属性值,其中属性值必须用单引号或者双引号括起来;一个元素可以有0到n个属性,但一个元素中不能出现同名属性,且属性名不能使用空格、冒号等特殊字符,必须以字母开头。

注释

xml的注释是以< !--快开始,以 -- >结束,注释的内容会被XML解释器忽略掉

接下来使用XML描述一个数据表中的数据,具体代码如下:

<?xml version="1.0" encoding="utf-8"?>
<employees>
  <employee eid="1">
    <ename>林黛玉</ename>
    <age>18</age>
  </employee>
  <employee eid="2">
    <ename>刘备</ename>
    <age>38</age>
  </employee>
  <employee eid="3">
    <ename>关羽</ename>
    <age>48</age>
  </employee>
</employees>

xml约束

在xml技术里,可以编写一个文档来约束一个xml文档的书写规范,这就是xml约束。常见的xml约束有:DTD和Schema,在日常开发中只要求会阅读和会引入,不用自己编写xml约束。

2 DTD约束

DTD文档类型定义,用来约束xml文档。规定xml文档中的元素的名称,子元素的名称和顺序,元素的属性等。

<!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 唯一的值 不能重复 值只能是字母或者下划线开头
-->

引入dtd文档到xml文档中的两种方式:

  • 内部dtd:将约束规则定义在xml文档中
  • 外部dtd:将约束的规则定义在外部的dtd文件中

接下来以student.xml为例:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE students SYSTEM "H:\jdbc_work\xml_task03\src\com\lagou\xml02\dtd\student.dtd">
<students>
    <student number="S1">
        <name>长海</name>
        <age>20</age>
        <sex></sex>
    </student>

    <student number="S2">
        <name>大玲子</name>
        <age>18</age>
        <sex></sex>
    </student>

</students>

3 Schema约束

Schema约束是最新的xml文档约束,要比DTD更加强大,是DTD的替代者,Schema本身也是XML文档,但是Schema文档的扩展名为xsd,而不是xml,Schema强大就强大在内置多种简单和复杂的数据类型,且支持命名空间(一个XML中可以引入多个约束文档)

Schema约束文档实例:

<?xml version="1.0" encoding="UTF-8" ?>
<xsd:schema xmlns="http://www.lagou.com/xml"
            xmlns:xsd="http://www.w3.org/2001/XMLSchema"
            targetNamespace="http://www.lagou.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="hehe_\d{4}"/>
        </xsd:restriction>
    </xsd:simpleType>
</xsd:schema>

xml中引入Schema约束,具体代码如下:

<?xml version="1.0" encoding="UTF-8" ?>
<students
        xmlns="http://www.lagou.com/xml"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.lagou.com/xml student.xsd"
>
    <student number="hehe_1234">
        <name>张三</name>
        <age>200</age>
        <sex>male</sex>
    </student>

    <student number="hehe_4567">
        <name>张三</name>
        <age>200</age>
        <sex>male</sex>
    </student>

</students>

4 XML解析

当我们定义完XML文档后,当想要通过程序来获得XML文档中的内容,就需要使用XML解析,在开发中比较常见的的解析方式是:

  • DOM:要求解析器将整个XML文档装载到内存中,并解析成一个Docunment对象,这种方式的优点是:元素和元素之间保留结构关系,可以进行增删改查;缺点就是XML文档过大,可能会存在内存泄漏情况
  • SAX:是一种速度更快,更加有效的方法,它是逐行扫描文档,一边扫描一边解析,以事件驱动的方式进行解析,没执行一行,都会触发对应的事件。优点是:占用内存少,处理速度快,可以处理大文件;缺点是:只能读,逐行解析后释放资源

基于上面两种解析方式,市面上就出现了解析器,根据不同的解析方式提供具体的实现,具体解析器有:

  • JAXP:支持DOM和SAX两种方式
  • DOM4J:一款优秀的解析器,应用于Java平台,采用Java集合框架并完全支持DOM、SAX和JAXP
  • Jsoup:一款Java的HTML解析器,也可以解析XML
  • PULL:Android内置的XML解析器

DOM4J的使用:

使用之前先导包,在介绍解析相关的API,使用核心类SaxReader加载XML文档获得Document,再通过Document对象获得根元素,然后就可以进行解析操作。

常用API如下:

  • SaxReader对象:read(...)方法加载执行xml文档

  • Document对象:getRootElemet()获得根元素

  • Element对象: elements(...) 获得指定名称的所有子元素,可以不指定名称

    ​ element(...) 获得指定名称的第一个元素,可不指定名称

    ​ getName(...)获得当前元素的元素名

    ​ attributeValue(...)获得指定属性名的属性值

    ​ elementText(...)获得指定名称元素的文本值

    ​ getText() 获得当前元素的文本内容

编写user.xsd Schema约束

<?xml version="1.0" encoding="UTF-8" ?>
<xsd:schema xmlns="http://www.lagou.com/xml"
            xmlns:xsd="http://www.w3.org/2001/XMLSchema"
            targetNamespace="http://www.lagou.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:minIn clusive 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{3}"/>
        </xsd:restriction>
    </xsd:simpleType>

</xsd:schema>

编写user.xml

<?xml version="1.0" encoding="UTF-8" ?>
<users
        xmlns="http://www.lagou.com/xml"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.lagou.com/xml user.xsd"
>
    <user id="001">
        <name>张百万</name>
        <age>25</age>
        <hobby>抽烟</hobby>
    </user>

    <user id="002">
        <name>于谦</name>
        <age>55</age>
        <hobby>烫头</hobby>
    </user>

    <user id="003">
        <name>小斌</name>
        <age>25</age>
        <hobby>喝酒</hobby>
    </user>


</users>

读取xml

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;

public class TestDOM4j {

    //获取XML文件中的 所有的元素名称(标签)
    @Test
    public void test1() throws DocumentException {

        //1.获取XML解析对象
        SAXReader reader = new SAXReader();

        //2.解析XML 获取 文档对象 document
        Document document = reader.read("H:\\jdbc_work\\xml_task03\\src\\com\\lagou\\xml03\\user.xml");

        //3.获取根元素
        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;
        }

    }

    //获取XML中标签的文本信息 和 属性信息
    @Test
    public void test2() throws DocumentException {

        //1.获取解析XML的 SAXReader
        SAXReader reader = new SAXReader();

        //2.获取文档对象
        Document document = reader.read("H:\\jdbc_work\\xml_task03\\src\\com\\lagou\\xml03\\user.xml");

        //3.获取根节点
        Element rootElement = document.getRootElement();

        //4.获取子节点 user
        List<Element> elements = rootElement.elements();

        //5.获取集合中的第一个 子节点
        Element user = elements.get(0);

        //6.获取节点中的文本信息
        String id = user.attributeValue("id");//获取属性 id的值
        String name = user.elementText("name");
        String age = user.elementText("age");
        String hobby = user.element("hobby").getText();

        //打印
        System.out.println(id + " " + name +" " + age + " " + hobby);
    }
}

5 xpath方式读取xml

xpath是一门在xml文档中查找信息的语言,使用xpath的好处是:不用想DO M4J那样在解析XML时只能一层一层解析,这在XML文件层数较多时就非常不方便,结合xpath就可以直接获取到某个元素。

xpath基本语法介绍:

语法介绍
/AAA/DDD/BBB表示一层一层的,AAA下面DDD下面的BBB
//BB表示和这个名称相同,只要名称和BBB相同,都得到
//*所有元素
BBB[1],BBB[last]前面表示第一个BBB元素,后一个表示最后一个BBB元素
//BB[@id]只要BBB元素上面有id属性,都得到
//BB[@id='b1']得到BBB元素上面有id属性等于b1的元素

API介绍:

  • selectSingleNode(query)查找和XPath查询匹配的一个节点 query是XPath查询串
  • selectNodes(query)得到的是xml根结点下所有满足xpath的节点
  • Node 节点对象

Xpath读取book.xml

book.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>

读取xml的代码

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;

public class XpathTest {
    @Test
    public void test1() throws DocumentException {
        SAXReader sr=new SAXReader();
        Document dm=sr.read("/Users/bijinxiong/IdeaProjects/jdbc/xml/src/book.xml");
        Node node = dm.selectSingleNode("bookstore/book/name");
        System.out.println("节点名"+node.getName());
        System.out.println("书名"+node.getText());
        Node node1 = dm.selectSingleNode("bookstore/book[2]/name");
        System.out.println("查询到的第二本书是:");
        System.out.println("节点名"+node1.getName());
        System.out.println("书名"+node1.getText());


    }
    @Test
    public void test2() throws DocumentException {
        SAXReader sr=new SAXReader();
        Document dm=sr.read("/Users/bijinxiong/IdeaProjects/jdbc/xml/src/book.xml");
        Node node = dm.selectSingleNode("bookstore/book/attribute::id");
        System.out.println("第一本书的id:"+node.getText());
        Node node1 = dm.selectSingleNode("bookstore/book[last()]/attribute::id");
        System.out.println("第一本书的id:"+node1.getText());
        Node node2 = dm.selectSingleNode("bookstore/book[@id='book2']");
        String name = node2.selectSingleNode("name").getText();
        System.out.println("id为book2的书名是"+name);
    }
    @Test
    public void test3() throws DocumentException {
        SAXReader sr=new SAXReader();
        Document dm=sr.read("/Users/bijinxiong/IdeaProjects/jdbc/xml/src/book.xml");
        List<Node> list = dm.selectNodes("//*");
        for(Node node:list){
            System.out.println("节点名:"+node.getName());
        }
        List<Node> list1 = dm.selectNodes("//name");
        for(Node node:list1){
            System.out.println("所有书名是"+node.getText());
        }
        List<Node> list2 = dm.selectNodes("bookstore/book[@id='book1']//*");
        for(Node node:list2){
            System.out.println(node.getName()+" "+node.getText());
        }
    }


}

6 JDBC自定义XML

创建自定义的JDBC配置文件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>

工具类

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.io.SAXReader;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class JDBCUtils {
    public static String DRIVERNAME;
    public static String URL;
    public static String USERNAME;
    public static String PASSWORD;
    static {
        SAXReader sr = new SAXReader();
        try {
            Document dc = sr.read("/Users/bijinxiong/IdeaProjects/jdbc/xml/src/jdbc_config.xml");
            DRIVERNAME=dc.selectSingleNode("/jdbc/property[@name='driverClass']").getText();
            URL=dc.selectSingleNode("/jdbc/property[@name='jdbcUrl']").getText();
            USERNAME=dc.selectSingleNode("/jdbc/property[@name='user']").getText();
            PASSWORD=dc.selectSingleNode("/jdbc/property[@name='password']").getText();
            Class.forName(DRIVERNAME);

        } catch (DocumentException | ClassNotFoundException e) {
            e.printStackTrace();
        }

    }
    public static Connection getConnection() throws SQLException {
        Connection con= DriverManager.getConnection(URL,USERNAME,PASSWORD);
        return con;

    }



}

测试类

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class test {
    public static void main(String[] args) throws SQLException {
        Connection con=JDBCUtils.getConnection();
        Statement statement = con.createStatement();
        String sql="select ename from employee  where eid=2 ";
        ResultSet resultSet = statement.executeQuery(sql);
        while (resultSet.next()){
            System.out.println("eid为2的人是:"+resultSet.getString("ename"));
        }

        if(null!=con&&null!=statement){
            statement.close();
            con.close();
        }

    }
}