XML的学习

108 阅读11分钟

一.XML基本介绍

XML(Extensible Markup Language)是一种标记语言,它允许用户定义自己的标签(或称为“元素”)来组织数据。XML被设计用来传输和存储数据,而不仅仅是展示数据。它是一种纯文本格式,意味着它可以用任何文本编辑器创建和编辑,同时也易于被计算机程序读取和处理。

1.1 XML的特点:

XML的主要特点包括:

  1. 可扩展性:XML允许用户根据需要定义自己的标签,这意味着它可以用于各种应用程序中,从简单的数据交换到复杂的业务逻辑。
  2. 自描述性:XML文档包含有关其内容的元数据(通过标签),这使得即使没有外部描述文档(如DTD或Schema),也能理解XML文档的结构。
  3. 结构化:XML文档通过嵌套标签来组织数据,形成树状结构,这种结构使得数据易于管理和访问。
  4. 跨平台性:由于XML是纯文本格式,因此它可以在任何操作系统和平台上使用,无需进行特殊转换。
  5. 多种用途:XML广泛应用于数据交换、配置文件、网络传输、软件文档等领域.

1.2 XML能做什么?

image.png

二.XML基本语法

1.1 基本语法

1.XML中必须进行文档声明
        version 版本信息
        endcoding 编码
2.xml的文档声明必须写在第一行

3.XML 中的元素标签 命名规则
   1.标签定义 不能使用空格 或者 冒号
   2.xml 标签名称 区分大小写
4.XML中有且只有一共根元素

5.元素体 可以是文本 或者 还是一个标签

6.属性是元素的一部分 只能出现在元素的开始标签中
        属性值必须使用单引号或者双引号包裹
           一个标签可以定义多个属性

1.2 自定义XML描述数据

<?xml version="1.0" encoding="UTF-8" ?>
<employees>
    <employee eid="2">
        <ename>林黛玉</ename>
        <age>20</age>
        <sex></sex>
        <salary>5000</salary>
        <empdate>2010-01-01</empdate>




    </employee>
   
    <employees>
        <employee eid="3">
            <ename>杜甫</ename>
            <age>20</age>
            <sex></sex>
            <salary>5000</salary>
            <empdate>2010-01-01</empdate>




        </employee>







    </employees>

1.3 XML约束

image.png

1.4 DTD约束

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

开发中,我们不会自己编写DTD约束文档

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

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子元素, + 代表至少一个
       #PCDATA: 是普通文本内容
       student (name,age,sex): student 标签中包含的子元素,按顺序出现
       ATTLIST: 用来定义属性
       student number ID #REQUIRED
        student子元素中 有一个ID属性叫做 number,是必须填写的
       ID: 唯一 值只能是字母或者下划线开头-->

1.5 引入DTD约束

image.png

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE sudents SYSTEM "student.dtd">
<students>
    <student number="s1">
        <name>长海</name>
        <age>20</age>
        <sex></sex>
    </student>

    <student number="s2">
        <name>狗剩</name>
        <age>21</age>
        <sex></sex>
    </student>
</students>

1.6 Schema约束

  1. Schema是新的XML文档约束, 比DTD强大很多,是DTD 替代者;
  2. Schema本身也是XML文档,但Schema文档的扩展名为xsd,而不是xml。
  3. Schema 功能更强大,内置多种简单和复杂的数据类型
  4. Schema 支持命名空间 (一个XML中可以引入多个约束文档

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

image.png

1.7 引入Schema约束

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

        xmlns="https://www.bilibili.com/xml"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema"
        xsi:schemaLocation="https://www.bilibili.com/xml student.xsd"
        >
    <student number="hehe_1234">
        <name>张三</name>
        <age>10</age>
        <sex>male</sex>
    </student>
    <student number="hehe_4567">
        <name>张三</name>
        <age>20</age>
        <sex>male</sex>
    </student>



</students>

三.XML解析

1.1 XML解析概述

解析XML文档是读取XML数据并提取所需信息的过程。这个过程可以通过不同的方式完成,主要取决于你的需求和所使用的编程语言。 XML解析主要分为两种类型:

  • DOM(Document Object Model)解析

    • DOM解析器将整个XML文档加载到内存中,并构建成一个树状结构(DOM树),其中的每个节点都对应XML文档中的一个元素、属性或文本等。
    • 优点:易于理解和使用,因为整个文档都被加载到内存中,所以可以通过编程方式访问文档的任何部分。
    • 缺点:对于大型文档,可能会消耗大量内存。
  • SAX(Simple API for XML)解析

    • SAX解析器是一个基于事件的解析器,它边读取XML文档边解析,占用内存少。
    • 当解析器遇到XML文档中的特定元素时,它会触发(或“抛出”)事件(如开始元素、结束元素、文本等),并允许应用程序对这些事件作出响应。
    • 优点:内存占用低,适用于处理大型文件。
    • 缺点:因为数据是按需读取的,所以可能难以访问文档中的随机位置。

1.2 DOM解析和SAX解析的区别:

DOM解析和SAX解析是XML文档解析的两种主要方式,它们在处理XML文档时有显著的区别。以下是DOM解析和SAX解析的主要区别:

1. 解析方式

  • DOM解析:DOM(Document Object Model)解析器会将整个XML文档加载到内存中,并构建一个树状结构(DOM树)。这个树状结构中的每个节点都对应XML文档中的一个元素、属性或文本等。开发者可以通过编程方式遍历这个DOM树,以访问或修改文档中的数据。
  • SAX解析:SAX(Simple API for XML)解析器是一种基于事件的解析器。它边读取XML文档边解析,不会将整个文档加载到内存中。当SAX解析器遇到XML文档中的特定元素时,它会触发(或“抛出”)事件(如开始元素、结束元素、文本等),并允许应用程序对这些事件作出响应。

2. 内存占用

  • DOM解析:由于DOM解析器将整个文档加载到内存中,因此它可能会消耗大量的内存,尤其是当处理大型XML文档时。
  • SAX解析:SAX解析器只占用很少的内存,因为它不会将整个文档加载到内存中。它只处理当前读取的部分,并在处理完成后立即释放资源。

3. 访问和修改能力

  • DOM解析:由于DOM树在内存中构建,因此开发者可以轻松地访问和修改文档中的任何部分。这使得DOM解析器非常适合需要频繁访问和修改XML数据的场景。
  • SAX解析:SAX解析器不提供对文档的随机访问能力。它只能按顺序读取文档,并在读取过程中触发事件。因此,SAX解析器不适合需要修改XML数据的场景,而更适合只需要读取数据的场景。

4. 灵活性

  • DOM解析:DOM解析器提供了丰富的API来访问和修改XML文档,使得开发者可以灵活地处理XML数据。
  • SAX解析:SAX解析器的灵活性相对较低,因为它主要依赖于事件处理机制。开发者需要编写事件处理器来响应SAX解析器触发的事件,并根据需要处理数据。

5. 适用场景

  • DOM解析:适用于需要频繁访问和修改XML数据的场景,以及当内存资源相对充足时。
  • SAX解析:适用于只需要读取XML数据,且内存资源有限的场景。特别是当处理大型XML文档时,SAX解析器通常是更好的选择。

1.3 常见的XML解析器

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

JAXP:sun公司提供的解析器,支持DOM和SAX两种思想 DOM4J:一款非常优秀的解析器.

Dom4j是一个易用的、开源的库,用于XML,XPath和XSLT。 它应用于Java平台,采用了Java集合框架并完全支持DOM,SAX和JAXP。

Jsoup:jsoup 是一款Java 的HTML解析器 ,也可以解析XML

PULL:Android内置的XML解析方式,类似SAX。

1.4 Dom4j解析器介绍

image.png

image.png 编写xsd文档 并且引用Schema约束

<?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="123">
        <name>张百万</name>
        <age>25</age>
        <hobby>抽烟</hobby>
    </user>
    <user id="002">
        <name>于谦</name>
        <age>25</age>
        <hobby>烫头</hobby>
    </user>

Dom4j解析XML代码:

package com.xml.xml01.xml03;

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

import java.util.List;


public class TestDOM4j {
    public static void main(String[] args) {
        try {
            new TestDOM4j().test1();
        } catch (DocumentException e) {
            throw new RuntimeException(e);
        }

    }
    //获取XML文件中的所有元素

    public void test1() throws DocumentException {


        //1.获取XML解析对象
        SAXReader reader = new SAXReader();
        //2.解析XML 获取文档对象 document
        Document document = reader.read("C:\Users\16925\IdeaProjects\xml_task03\xml_task031\src\com\xml\xml01\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> elements1 = element.elements();
            for (Element element1 : elements1) {
                System.out.println("user标签下的子节点"+element1.getName());

            }
                    break;
        }
    }
    //获取XML中标签的文本信息和属性信息
    public void test2() throws DocumentException {
       //1.获取解析XML的SAXReader
       SAXReader reader = new SAXReader();
       //2.获取文档对象
        Document document = reader.read("C:\Users\16925\IdeaProjects\xml_task03\xml_task031\src\com\xml\xml01\xml03\user.xml");
        //3.获取根节点
        Element rootElement = document.getRootElement();
        //4.获取子节点 user
        List<Element> elements= rootElement.elements();
        //5.获取集合中的第一个子节点
        Element user = elements.get(0);
        //6.获取节点中的文本信息4
        String id = user.attributeValue("id");
        String name = user.attributeValue("name");
        String age = user.attributeValue("age");
        String hobby = user.element("hobby").getText();
        //打印
        System.out.println(id+""+name+""+age+""+ hobby);

    }
}

1.5 XPath

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

XPath 的好处

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

使用dom4j支持xpath的操作的几种主要形式

image.png

常用方法:

image.png

(一).Xpath语法获取单个节点信息

public void test1() throws DocumentException {
    /**
     * 1使用selectSingleNode() 方法 查询指定节点信息
     */
    //1.创建XML解析对象
    SAXReader reader = new SAXReader();
    //2.解析XML 获取 文档对象
    Document document = reader.read("C:\Users\16925\IdeaProjects\xml_task03\xml_task031\src\com\xml\xml01\xml04\book.xml");
    //3.通过selectSingLeNode() 方法获取name节点
    Node node1 = document.selectSingleNode("/bookstore/book/name");
    System.out.println("节点的名称:"+node1.getName());
    System.out.println("书名:"+node1.getText());

    //4.获取第二本的书名
    Node node2 = document.selectSingleNode("/bookstore/book[2]/name");
    System.out.println("第二本书的书名:"+node2.getText());
}

(二).Xpath语法获取属性值

/**
 * 2使用 selectSIngLeNode() 方法 获取属性值 或者 通过属性值获取到节点的信息
 */
public void test2() throws DocumentException {
    //1.创建解析器对象
    SAXReader sr = new SAXReader();
    //2.获取文档对象
    Document document = sr.read("C:\Users\16925\IdeaProjects\xml_task03\xml_task031\src\com\xml\xml01\xml04\book.xml");
    //3.获取第一个book节点的 id属性的值
    Node node1 = document.selectSingleNode("/bookstore/book/attribute::id");
    System.out.println("第一个book的id值为: " + node1.getText());
    //4.获取最后一个book节点的 id属性的值
    Node node2 = document.selectSingleNode("/bookstore/book[last()]/attribute::id");
    System.out.println("最后一个book节点的id值为: " + node2.getText());
    //5.获取id属性值为 book2的 书名
    Node node3 = document.selectSingleNode("/bookstore/book[@id='book2']");
    String name = node3.selectSingleNode("name").getText();
    System.out.println("id为book2的书名是: " + name);

}

(三).Xpath语法获取多个节点信息

public void test3() throws DocumentException {
    //1.创建解析器对象
    SAXReader sr = new SAXReader();
    //2.获取文档对象
    Document document = sr.read("C:\Users\16925\IdeaProjects\xml_task03\xml_task031\src\com\xml\xml01\xml04\book.xml");

    //3.获取所有节点,打印节点名
    List<Node> list = document.selectNodes("//*");
    for (Node node : list) {
        System.out.println("节点名: " + node.getName());
    }
    //4.获取所有的书名
    List<Node> names = document.selectNodes("//name");
    for (Node name : names) {
        System.out.println(name.getText());
    }
    //5.获取指定 id值为book1的节点的所有 内容
    List<Node> book1 =
            document.selectNodes("/bookstore/book[@id='book1']//*");
    for (Node node : book1) {
        System.out.println(node.getName()+" = " + node.getText());
    }
}

四.配置式JDBCUtils(JDBC自定义XML)

创建自定义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">123123</property>




</jdbc>

编写工具类:

package com.xml.xml01.xml05;

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

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

public class JDBCUtills {
    //1.定义字符串变量 保存连接信息
    public static String DRIVERNAME;
    public static String URL;
    public static String USER;
    public static String PASSWORD;
    //2.静态代码块
    static {
            //使用XPath语法 对XML中的数据进行读取
        SAXReader reader = new SAXReader();
        try {
            Document document = reader.read("C:\Users\16925\IdeaProjects\xml_task03\xml_task031\src\com\xml\xml01\xml05\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']");
            URL = url.getText();
            //3.获取用户名
            Node user = document.selectSingleNode("/jdbc/property[@name='user']");
            USER = user.getText();
            //4.获取密码
            Node password = document.selectSingleNode("/jdbc/property[@name='password']");
            PASSWORD = password.getText();
            //注册驱动
            Class.forName(DRIVERNAME);

        } catch (Exception e) {
            throw new RuntimeException(e);

            //
        }


    }
    //获取连接
    public static Connection getConnection(){

        try {
            Connection connection = DriverManager.getConnection(URL, USER, PASSWORD);
            return connection;
        } catch (SQLException e) {
            throw new RuntimeException(e);
            return null;
        }


    }
}

测试工具类:

package com.xml.xml01.xml05;

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

public class TestJDBC {
    //查询所有员工信息
    public static void main(String[] args) throws SQLException {
        //1.获取连接
        Connection connection = JDBCUtills.getConnection();
        //2.获取Statement对象
        Statement statement = connection.createStatement();
        ResultSet resultSet = statement.executeQuery("select * from employee");
        //3.处理结果集
        while (resultSet.next()){

            String name = resultSet.getString("ename");
            System.out.println("员工的姓名:"+name);


        }
        //4.关闭资源
        resultSet.close();
        statement.close();
        connection.close();
    }
}