配置文件解析之XML介绍和用法

0. 配置文件介绍和分类

介绍 :

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qAtAvwAf-1643258138005)(img\1.png)]

  • 好处 :
    • 可以让项目中使用的数据, 灵活的加载和更变, 实现解耦
分类 :
  • Properties : 常用于一对一的存储
    • 键值对
    • username=root
    • password=123456
  • xml : 常用于一对多的存储

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5mf9aKU6-1643258138006)(\img\2.png)]

1. XML 介绍

​ XML的全称为(EXtensible Markup Language),是一种可扩展标记语言。

  • 标记语言:通过标签来描述数据的一门语言(标签有时我们也将其称之为元素)
  • 可扩展:标签的名字是可以自己定义的
优势 :
  • 作为软件的配置文件
  • 用于进行存储数据和传输数据
    • 传输的理解, 主要还是喜欢它里面的格式

2. XML 语法

语法规则 :
  • 创建

    • 就是创建一个XML类型的文件,要求文件的后缀必须使用xml,如hello_world.xml
  • 文档声明

    文档声明必须是第一行第一列

    <?xml version="1.0" encoding="UTF-8" ?>
    • version:该属性是必须存在的
    • encoding:该属性不是必须的
    • 打开当前xml文件的时候应该是使用什么字符编码表(一般取值都是UTF-8)
    • standalone: 该属性不是必须的,描述XML文件是否依赖其他的xml文件,取值为yes/no
  • 标签规则

    • 必须存在一个根标签,有且只能有一个
  • 标签由一对尖括号和合法标识符组成

    <student>
    
  • 标签必须成对出现

    <student> </student>
    前边的是开始标签,后边的是结束标签
    
  • 特殊的标签可以不成对, 但是必须有结束标记

    <address/>
    
  • 标签中可以定义属性,属性和标签名空格隔开,属性值必须用引号引起来

    <student id="1"> </student>
    
  • 标签需要正确的嵌套

    这是正确的: 
    <student id="1"> 
        <name>张三</name>
    </student>
        
        
    这是错误的: 
    <student id="1">
        <name>张三
        </student>
    </name>
    
  • 细节

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FYpDSeh8-1643258138006)(img\3.png)]

案例 :
  • 需求 : 编写一个城市对应区的 xml 文件
    • 城市: city
    • 区域 : area
北京市 :
	东城区
	西城区
	朝阳区
	海淀区
	昌平区

3. XML 约束 (了解)

这东西以后都不会自己写

介绍 :
  • 用来限定xml文件中可使用的标签以及属性
分类 :
  • DTD 约束
  • schema 约束
DTD 约束

编写DTD约束

  • 步骤

    1. 创建一个文件,这个文件的后缀名为.dtd

    2. 看xml文件中使用了哪些元素

      <!ELEMENT> 可以定义元素
    3. 判断元素是简单元素还是复杂元素

      简单元素:没有子元素。
      复杂元素:有子元素的元素;

  • 代码实现

    <!ELEMENT persons (person)>
    <!ELEMENT person (name,age)>
    <!ELEMENT name (#PCDATA)>
    <!ELEMENT age (#PCDATA)>
    
  • 引入DTD约束

    • 引入本地dtd

      <!DOCTYPE 根元素名称 SYSTEM 'DTD文件的路径'>
      
    • 在xml文件内部引入

      <!DOCTYPE 根元素名称 [ dtd文件内容 ]>
      
    • 引入网络dtd

      <!DOCTYPE 根元素的名称 PUBLIC "DTD文件名称" "DTD文档的URL">
      
    • 引入本地DTD约束

      // 这是persondtd.dtd文件中的内容,已经提前写好
      <!ELEMENT persons (person)>
      <!ELEMENT person (name,age)>
      <!ELEMENT name (#PCDATA)>
      <!ELEMENT age (#PCDATA)>
      
      // 在person1.xml文件中引入persondtd.dtd约束
      <?xml version="1.0" encoding="UTF-8" ?>
      <!DOCTYPE persons SYSTEM 'persondtd.dtd'>
      
      <persons>
          <person>
              <name>张三</name>
              <age>23</age>
          </person>
      
      </persons>
      
    • 在xml文件内部引入

      <?xml version="1.0" encoding="UTF-8" ?>
      <!DOCTYPE persons [
              <!ELEMENT persons (person)>
              <!ELEMENT person (name,age)>
              <!ELEMENT name (#PCDATA)>
              <!ELEMENT age (#PCDATA)>
              ]>
      
      <persons>
          <person>
              <name>张三</name>
              <age>23</age>
          </person>
      
      </persons>
      
    • 引入网络dtd

      <?xml version="1.0" encoding="UTF-8" ?>
      <!DOCTYPE persons PUBLIC "dtd文件的名称" "dtd文档的URL">
      
      <persons>
          <person>
              <name>张三</name>
              <age>23</age>
          </person>
      
      </persons>
      
Schema 约束
  • schema 和 dtd 的区别

    1. schema约束文件也是一个xml文件,符合xml的语法,这个文件的后缀名.xsd
    2. 一个xml中可以引用多个schema约束文件,多个schema使用名称空间区分(名称空间类似于java包名)
    3. dtd里面元素类型的取值比较单一常见的是PCDATA类型,但是在schema里面可以支持很多个数据类型
    4. schema 语法更加的复杂

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uhA7AYDM-1643258138007)(\img\4.png)]

  • 编写schema约束

1. 创建一个文件,这个文件的后缀名为.xsd

2. 定义文档声明

3. schema文件的根标签为: <schema>

4.<schema>中定义属性:
        xmlns=http://www.w3.org/2001/XMLSchema
        
5.<schema>中定义属性:
        targetNamespace = 唯一的url地址,指定当前这个schema文件的名称空间
            理解: 起个名, 顺带打广告

6.<schema>中定义属性:
	elementFormDefault="qualified“,表示当前schema文件是一个质量良好的文件
	
7. 通过element定义元素

8. 判断当前元素是简单元素还是复杂元素
示例 :

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-23KUs9Sa-1643258138007)(\img\5.png)]

引入 :
<stus xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xmlns="http://www.mhys.com"
      xsi:schemaLocation="http://www.mhys.com stus.xsd"
>
    <student>
        <name>张三</name>
        <age>23</age>
    </student>

</stus>

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CnjSGP0e-1643258138011)(img\23.png)]

4. XML解析

  • 解析的两种方式
    • SAX 解析
    • DOM 解析

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rqAMZurs-1643258138011)(\img\6.png)]

在这里插入图片描述

准备动作
  1. 导入 dom4j-1.6.1.jar 包
  2. 获取 Document 对象
SAXReader reader = new SAXReader();
Document document = reader.read(new File("day15-code\\src\\xml\\stus.xml"));
System.out.println(document);
方法介绍

在这里插入图片描述

示例代码
package com.ligong.start;

import com.ligong.domain.Student;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.List;

public class Test {
    public static void main(String[] args) throws DocumentException, FileNotFoundException {
        SAXReader reader = new SAXReader();
        Document document = reader.read(new File("mC\\src\\xml\\stus.xml"));

        ArrayList<Student> list = new ArrayList<>();

        // 1. 获取根标签
        Element rootElement = document.getRootElement();

        // 2. 获取根标签下的所有子标签
        List<Element> student = rootElement.elements("student");

        // 3. 遍历集合
        for (Element element : student) {
            // 4. 获取标签属性
            String id = element.attributeValue("id");
            // 5. 获取name标签的值
            String name = element.element("name").getText();
            // 6. 获取age标签的值
            String age = element.element("age").getText();
            // 7. 封装为Student学生对象
            Student stu = new Student(name, Integer.parseInt(age));
            // 8. 添加到集合
            list.add(stu);
        }

        list.forEach(s -> System.out.println(s));
    }
}

5. Xpath检索

  • Dom 的弊端
    • 如果需要从XML文件中检索需要的某个信息(如name)怎么解决?
      • Dom4j需要进行文件的全部解析,然后再寻找数据
      • Xpath 技术更加适合做信息检索
介绍
  • XPath在解析XML文档方面提供了独树一帜的路径思想,更加优雅,高效
  • XPath使用路径表达式来定位XML文档中的元素节点或属性节点

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WlDi8wdw-1643258138015)(img\11.png)]

准备动作 :
  • 导入 jaxen-1.1-beta-6.jar 包
    • 主要 : 这东西依赖于 Dom4J 用的时候都得有

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rzJAR6Q0-1643258138015)(img\12.png)]

SAXReader reader = new SAXReader();
Document document = reader.read(new File("mC\\src\\xml\\stus.xml"));

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sQLisHhh-1643258138015)(img\13.png)]

绝对路径示例代码 :

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TjSQnwNe-1643258138015)(img\14.png)]

package com.ligong.start;

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

import java.io.File;
import java.io.FileNotFoundException;
import java.util.List;

public class Test {
    public static void main(String[] args) throws DocumentException, FileNotFoundException {
        SAXReader reader = new SAXReader();
        Document document = reader.read(new File("mC\\src\\xml\\stus.xml"));

        // 获取单个节点
        Node node = document.selectSingleNode("/students");
        System.out.println(node.getText());

        // 获取多个节点
        List<Element> list = document.selectNodes("/students/student/name");
        for (Element element : list) {
            System.out.println(element.getText());
        }
    }
}

相对路径示例代码 :
  • 相对于谁 : 根节点 rootElement

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dk8EEVJj-1643258138016)(img\15.png)]

package com.ligong.start;

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

import java.io.File;
import java.io.FileNotFoundException;
import java.util.List;

public class A {
    public static void main(String[] args) throws DocumentException, FileNotFoundException {
        SAXReader reader = new SAXReader();
        Document document = reader.read(new File("mC\\src\\xml\\stus.xml"));


        // 相对路径: 相对于根节点
        Element rootElement = document.getRootElement();

        // 获取单个
        Node node = rootElement.selectSingleNode("./student/name");
        System.out.println(node.getText());

        // 获取多个节点
        List<Element> list = rootElement.selectNodes("./student/age");
        for (Element element : list) {
            System.out.println(element.getText());
        }
    }
}
全文检索示例代码 :

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xCFoDMZA-1643258138016)(img\16.png)]

package com.ligong.start;

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

import java.io.File;
import java.io.FileNotFoundException;
import java.util.List;

public class A {
    public static void main(String[] args) throws DocumentException, FileNotFoundException {
        SAXReader reader = new SAXReader();
        Document document = reader.read(new File("mC\\src\\xml\\stus.xml"));

        // 获取多个节点 - 全文检索
        List<Element> list1 = document.selectNodes("//name");
        for (Element element : list1) {
            System.out.println(element.getText());
        }

        System.out.println("---------------------------");

        // 获取多个节点 - 全文检索 / (父节点下面的子节点)
        List<Element> list2 = document.selectNodes("//student/name");
        for (Element element : list2) {
            System.out.println(element.getText());
        }

        System.out.println("---------------------------");

        // 获取多个节点 - 全文检索 / (父节点下面的子节点, 孙子节点, 重孙子...)
        List<Element> list3 = document.selectNodes("//student//name");
        for (Element element : list3) {
            System.out.println(element.getText());
        }

    }
}
属性查找示例代码:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8pGoKqnB-1643258138016)(\img\17.png)]

package com.ligong.start;

import org.dom4j.*;
import org.dom4j.io.SAXReader;

import java.io.File;
import java.io.FileNotFoundException;
import java.util.List;

public class A {
    public static void main(String[] args) throws DocumentException, FileNotFoundException {
        SAXReader reader = new SAXReader();
        Document document = reader.read(new File("mC\\src\\xml\\stus.xml"));

        // 全文检索 : 所有属性
        List<Attribute> list1 = document.selectNodes("//@id");
        for (Attribute attribute : list1) {
            System.out.println(attribute.getText());
        }

        System.out.println("---------------------------");

        // 全文检索 : 带有指定属性的子标签
        List<Element> list2 = document.selectNodes("//student[@id]");
        for (Element element : list2) {
            System.out.println(element.getName());
        }

        System.out.println("---------------------------");

        // 全文检索 : 带有指定属性的子标签 + 标签值
        List<Element> list3 = document.selectNodes("//student[@id=2]");
        for (Element element : list3) {
            System.out.println(element.element("name").getText());
        }

    }
}
总结 :
  • 准备两个 jar 包
dom4j-1.6.1.jar
jaxen-1.1-beta-6.jar
    
SAXReader reader = new SAXReader();
Document document = reader.read(new File("xxxx"));
  • 主要玩的两个方法 :
document.selectSingleNode("路径");
document.selectNodes("路径");
  • 路径的两种写法 :
绝对路径 : 逐级查找 
相对路径 : 相对于根节点  rootElement  (了解)
    
    				  ./student/name
    
   					  注意: 必须使用根标签对象, 调用方法.
  • 全文检索 :
//name : 文件里所有的都找出来, 不考虑子父标签
//student/name : 找指定父节点下面的子标签
//student//name : 找父节点下面所有后辈的子标签
  • 带属性查找
//@id : 文件里所有的都找出来, 不考虑子父标签
		- 注意: 这东西玩的是属性, Attribute
            
//student[@id] : 找带有id属性的student标签
        - 注意: 找到的是标签, Element
            
//student[@id='2'] : 跟上面一样, 找的是标签, 就是带有具体属性值        

6. 工厂设计模式

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-M5xxaXYe-1643258138017)(img\18.png)]

public class ComputerFactory {
    /**
       定义一个方法,创建对象返回
     */
    public static Computer createComputer(String info){
        switch (info){
            case "huawei":
                Computer c = new Huawei();
                c.setName("huawei pro 16");
                c.setPrice(5999);
                return c;
            case "mac":
                Computer c2 = new Mac();
                c2.setName("MacBook pro");
                c2.setPrice(11999);
                return c2;
            default:
                return null;
        }
    }
}
  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Code攻城狮

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值