Day15-XML


title: Day15-XML
date: 2020-07-27 11:26:38
tags:


XML

Extensible Market Language 可扩展标记语言

  1. XML是特殊文件形式,结构化文件
  2. 做数据保存
  3. 做信息交互和共享的(重点,数据传输)
  4. 做系统的配置文件数据

XML作用

  1. 数据交换:不同的计算机语言之间,不同的操作系统之间,不同的数据库之间,进行数据交换

XML数据交换

  1. 配置文件:在后期我们主要用于各种框架的配置文件

    <?xml version="1.0" encoding="utf-8" ?>
    <server-config>
        <default-config>
            <property name = "driverClass">com.zimo.jdbc.Driver</property>
            <property name = "jdbcUrl">jdbc:mysql://localhost:3306/test</property>
            <property name = "user">root</property>
            <property name = "password">123456</property>
        </default-config>
    </server-config>
    

XML的特点

  • 用于数据交互,用于数据的存储,用于做系统的配置文件
  • 区分大小写
  • 非常严谨,只要有错误,解析器就不能解析
  • 可以扩展的,所有的标签都是程序员自己创建出来
  • XML文件的后缀为.xml

注意:XML以后通过Java来进行解析,很少直接在浏览器上显示

XML由七种组成元素构成:

  1. 声明(抬头):必须在第一行

    version:指定XML文件使用的版本,取值是1.0

    encoding:当前xml使用的编码(字符集)

    standalone:指定当前这个XML文件是否是一个独立的文件,省略的,默认是独立文件

  2. 元素(标签)

    语法:<a>开头 内容 </a>结尾

    主体部分:标签分为有主体和没有主体的两种,如果没有主题,标签一定要结束

    大小写:区分大小写

    命名:不能由空格,不能有冒号

    根元素:有且只有一个根元素

  3. 属性

    例如:<person id = "10086">

  4. 注释

  5. 实体字符

实体字符

  1. CDATA字符数据区

  2. 处理指令

<?xml version="1.0" encoding="UTF-8" ?>		<!-- 1.声明 抬头 -->
<!-- 2.注释 这就是注释 -->
<!-- 3.标签(元素) 一个XML文件只能有一个根标签 -->

<!-- 7.实体字符 导入外部css样式,控制xml效果,没用,xml不是为了展示 -->
<?xml-stylesheet type="text/css" href="student.css" ?>
<Student>
    <!-- 4.属性信息 id,desc -->
    <name id = "1" desc = "高富帅">zimo</name>
    <age>18</age>
    <!-- 5.实体字符 不能使用特殊字符,必须使用转义实体字符 -->
    <sql><!-- select * from student where age > 18 && age < 30; -->
        select * from student where age &gt; 18 &amp;&amp; age &lt; 30;
    </sql>
    
    <!-- 6.实体字符 -->
    <sql>
        <![CDATA[
			select * from student where age > 18 && age < 30;
	   ]]>
    </sql>
</Student>

版本说明

w3c在1988年2月发布1.0版本,2004年2月发布1.1版本,因为1.1不能向下兼容1.0版本,所以1.1没有人用,在2004年2月w3c又发布了1.0版本的第三版

  • 小结:

    1. 声明有哪两个常用属性?

      version、encoding

    2. 一个XML有几个根元素?

      一个

    3. XML标签命名不能有什么符号?

      空格、冒号

  • 一个良好的XML有以下特点

    1. 必须以XML声明开头
    2. 必须拥有唯一的根元素
    3. 开始标签必须与结束标签相匹配
    4. 元素对大小写敏感
    5. 所有的元素必须关闭
    6. 所有的元素必须正确地嵌套
    7. 特殊字符必须使用实体字符或使用字符数据区

XML约束:

XML文件的标签和属性可以随意扩展,有时我们必须要限制每个文档有哪些元素,每个元素都有哪些子元素,每个元素有哪些属性等,从而保证XML文档格式和数据的正确性和规范性

DTD约束

  1. DTD:Document Type Definiation 文档类型定义
  2. 作用:纯文本文件,指定了XML约束规则
导入DTD文件的两种格式 说明
系统DTD文件,通常个人或公司内部使用
公有的DTD文件,在互联网上广泛使用的DTD

如:hibernate框架的导入方式

<!DOCTYPE hibernate-configuration PUBLIC						  <!-- hibernate-configuration 根元素 -->
"-//Hibernate/Hibrenate Configuration DTD 3.0//EN"				   <!-- DTD文件描述 -->
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">		<!-- DTD文件 -->

<hibernate-configuration>

</hibernate-configuration>

自定义books.dtd文件

<!ELEMENT	书架	(书+) >					// 书架
<!ELEMENT		(书名, 作者, 售价) >		  // 至少一本书
<!ELEMENT	书名	(#PCDATA) >				 // 书名
<!ELEMENT	作者	(#PCDATA) >				 // 作者
<!ELEMENT	售价	(#PCDATA) >				 // 售价

使用books.dtd文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE 书架 SYSTEM "books.dtd">
<书架>
	<>
		<书名></书名>
		<作者></作者>
		<售价></售价>
	</>
</书架>

DTD约束:只能约束标签,无法约束类型

Schema约束

  • DTD的不足:
    1. 不能验证数据类型
    2. 因为DTD是一个文本文件,本身不能验证是否正确

Schema特点

  1. 约束文件本身也是一个XML文件,它本身也会被其它xsd文档约束
  2. 内置多种数据类型,可以检查数据类型是否正确
  3. 支持命名空间,一个XML文件可以同时引入多个xsd的约束文件,让约束规则重用
  4. 扩展名为xsd:XML Schema Definition

约束文件扩展名XML模式定义:xsd

约束文件本身也是XML文件,所以也有根元素,根元素名字叫:Schema

模式文档和实力文档

  • 模式文档:指定约束的XML文档(类似:类)
  • 实例文档:被约束的XML文档(类似:对象)
<?xml version="1.0" encoding="UTF-8" ?>
<schema xmlns="http://www.w2.org/2001/XMLSchema"
        targetNamespace="http://www.zimo.cn"
        elementFormDefault="qualified">
<!-- targetNamespace:声明约束文档的地址(命名空间) -->
	<element name = "书架">
		<!-- 写子元素 -->
		<complexType>
			<!-- maxOccurs='unbounded':书架下的子元素可以有任意多个 -->
			<sequence maxOccurs='unbounded'>
				<element name="">
					<!-- 写子元素 -->
					<complexType>
						<!-- 子元素必须有序 -->
						<sequence>
							<element name="书名" type='string' />
							<element name="作者" type='string' />
							<element name="售价" type='double' />
						</sequence>
					</complexType>
				</element>
			</sequence>
		</complexType>
	</element>
</schema>
<?xml version="1.0" encoding="UTF-8" ?>
<书架 xmlns="http://www.zimo.cn"
	 xmlns:xsi="http://www.w2.org/2001/XMLSchema"
     xsi:schemaLocation="http://www.zimo.cn books.xsd">
	<>
        <书名>11</书名>
        <作者>aa</作者>
        <售价>99.8</售价>
	</>
	<>
        <书名>22</书名>
        <作者>bb</作者>
        <售价>88.8</售价>
	</>
</书架>

XML的解析方式

  1. DOM解析:文档对象模型(面向对象解析方式)
    • 优点:将整个XML文件加载到内存中,生成DOM树,可以随意访问任意节点
    • 缺点:占内存,XML过大可能会内存溢出
  2. SAX解析:
    • 事件驱动型解析方式,读取一行就解析一行,释放内存。可以解析任意大小的XML文件
    • 缺点:使用过不能再次访问,不能修改,只能查询

Java中的DOM解析开发包

  1. JAXP:Oracle官方提供API,同时支持DOM和SAX
  2. JDOM:开源项目,基于树形结构,利用纯Java的技术对XML文档实现解析、生成、序列化及多种操作
  3. Dom4j:是JDOM升级版,性能优异,功能强大,使用简单,性能超过sun公司的dom技术,Habrenate也是用它读写配置
  4. Jsoup:是一款Java和HTML和XML解析器,可以解析URL地址、HTML文本内容。

DOM4j中DOM树的API

组成 说明
Document 当前解析的XML文档对象
Node XML中节点,它是其他所有节点对象的父接口
Element 代表一个元素(标签)
Attribute 代表一个属性
Text 代表标签中文本

Dom4j安装步骤

  1. 下载dom4j框架,jar包
  2. 把dom4j核心jar包导入项目
  3. 项目中创建文件夹:lib
  4. 将dom4j.jar复制到lib中
  5. 在jar文件夹上右键,Add As Library
  6. 类中导包使用
  • Java提供了Class下的一个方法:public InputStream getResourceAsStream(String path)

    | – 用于加载文件称为一个字节输入流返回!!

  • Document文档:

    • Element getRootElement():获取根元素
    • String getName():取元素名称
    • List<Element> elements():获取当前元素下的全部子元素(一级)
    • List<Element> elements(String name):获取当前元素下指定名称的全部子元素(一级)
    • Element element(String name):获取当前元素下的指定名称的某个子元素,默认取第一个
  • Element元素的API:

    • List<Attribute> attributes():获取元素的全部属性对象
    • Attribute attribute(String name):根据名称获取某个元素的属性对象
    • String attributeValue(String var1):直接获取某个元素的某个属性名称的值
  • Attribute对象的API:

    • String getName():获取属性名称
    • String getValue():获取属性值
  • Element:

    • String elementText(String name):可以直接获取当前元素的子元素的文本内容
    • String elementTextTrim(String name):去前后空格,直接获取当前元素的子元素的文本内容
    • String getText():直接获取当前文本内容
    • String getTextTrim():去前后空格,直接获取当前文本内容

案例:

/* Contact类 */
/**
 *	<contact id = "1" vip = "true">
 *	<name>潘金莲</name>
 *	<sex>女</sex>
 *	<email>[email protected]</email>
 *	</contact>
 */
public class Contact{
    
    
    private int id;
    private boolean vip;
    private String name;
    private char sex;
    private String email;
    public Contact(){
    
    
    }
    public Contact(int id, boolean vip, String name, char sex, String email){
    
    
        this.id = id;
        this.vip = vip;
        this.name = name;
        this.sex = sex;
        this.email = email;
    }
    // 各个属性的get,set方法.....
}
package com.zimo.Dom4j案例解析;
/**
 *	Dom4j解析XML文件:Contacts.xml成为一个Java对象(集合对象)
 *	Contacts.xml 解析成 ===>>> List<Contact>
 *	分析:
 *		1.定义一个联系人封装联系人数据
 *		2.解析成List集合
 */

public class Dom4JDemo{
    
    
    public static void main(String args[]) throws Exception{
    
    
        // 1.创建一个dom4j的解析器对象:代表整个dom4j框架
        SAXReader sa = new SAXReader();
        
        // 2.通过解析器对象去加载xml文件数据,成为一个document文档树对象
        Document d = sa.read(new File("zimo/src/Contacts.xml"));
        
        // 3.获取根元素
        Element eRoot = d.getRootElement();
        
        // 4.获取根元素下的全部子元素
        List<Element> eSon = eRoot.elements();
        
        // 5.遍历子元素 封装成list集合对象
        List<Contact> conList = new ArrayList();
        if(eSon != null && eSon.size() > 0){
    
    
            for(Element e : eSon){
    
    
                int id = Integer.valueOf(e.attributeValue("id"));
                boolean vip = Boolean.valueOf(e.attributeValue("vip"));
                String name = String.valueOf(e.elementText("name"));
                char sex = e.elementText("sex").charAt(0);
                String email = String.valueOf(e.elementText("email"));
                Contact contact = new Contact(id,vip,name,sex,email);
                conList.add(contact);
            }
        }
    }
}

Dom4j中的XPath

作用:一种用于快速查找XML元素的路径表达式,是用于方便的检索XML文件中的信息

  • XPath使用步骤

    1. 导入dom4j框架(XPath依赖dom4j技术)
    2. 导入XPath独有的框架包。jaxen.jar
  • XPath常用的API:

    • List<Node> selectNodes(String var1):检索出一批节点集合
    • Node selectSingleNode(String var1):检索出一个节点返回
  • XPath提供四种检索数据的写法

    1. 绝对路径:/根元素/子元素/子元素

    2. 相对路径:./子元素/子元素(.代表了当前元素)

    3. 全文搜索:

      //元素 在全文查找这个元素

      //元素1/元素2 在全文招元素1下面一级元素2

      //元素1//元素2 在全文找元素1下面的全部元素2

    4. 属性查找:

      //@属性名称 在全文检索属性对象

      //元素[@属性名称] 在全文检索包含该属性的元素对象

      //元素[@属性名称=值] 在全文检索包含该属性的元素且属性值为该值的元素对象

public class Dom4JDemo{
    
    
    public static void main(String args[]) throws Exception{
    
    
        // 1.创建一个dom4j的解析器对象
        SAXReader sa = new SAXReader();
        // 2.通过解析器对象去加载xml文件数据,成为一个document文档树对象
        InputStream is = Dom4JDemo.class.getResourceAsStream("/Contacts.xml")
        Document d = sa.read(is);
        
        // 3.1 使用绝对路径定位全部的name名称
        List<Node> nameNodes = d.selectNodes("/contact/name");	// 从文档根路径开始
        for(Node n : nameNode){
    
    
            System.out.println(n.getText());
        }
        --------------------------------------------------------------------------
        // 3.2 使用相对路径定位
        // 得到根元素对象
        Element root = document.getRootElement();
        // 从根元素开始检索
        List<Node> nameNodes = root.selectNodes("./name");
        --------------------------------------------------------------------------
        // 3.3全文检索
        List<Node> nameNodes = document.selectNodes("//name");		// 全文所有name节点
        List<Node> nameNodes = document.selectNodes("//contact/name");		// 全文所有contact/name节点
        List<Node> nameNodes = document.selectNodes("//contact//name");		// 全文contact下所有name节点
        --------------------------------------------------------------------------
        // 3.3全文检索-所有属性
        List<Node> attr = document.sattelectNodes("//@id");			// 全文所有id属性对象
        for(Node att : attr){
    
    
            Attribute a = (Attribute) att;
            System.out.println(n.getText());
        }
        List<Node> nodeEles = document.selectNodes("//contact[@id]");		// 全文所有contact下包含id属性的
        for(Node nodeEles : nodeEles){
    
    
            System.out.println(nodeEles.getName());
        }
        Node nodeEle = document.selectSingleNode("//contact[@id = 1]");		// 全文所有contact下包含id = 1属性的
        Element ele = (Element) nodeEle;
        System.out.println(ele.elementTextTrim("name"));
}

解析MyBatis配置文件

sqlMapConfig

public class ParseXMLConfig{
    
    
    public void parseXML() throws Exception{
    
    
        // 1.创建一个解析器对象
        SAXReader sr = new SAXReader();
        // 2.加载类路径下的xml文件成为一个document文档对象
        Document d = sr.read(ParseXMLConfig.class.getResourceAsStream("/sqlMapConfig.xml"));
        // 3.得到根元素对象
        Element root = d.getRootElement();
        // 4.获取子元素environments
        Element env = root.element("environments");
        // 5.获取子元素environment
        Element en = env.element("environment");
        // 6.获取子元素dataSource
        Element data = en.element("dataSource");
        // 7.获取dataSource下的全部子元素
        List<Element> properties = data.elements();
        // 8.遍历属性
        for(Element p : properties){
    
    
            System.out.println(p.attributeValue("name") + "===" + p.attributeValue("value"))
        }
    }
}

工厂模式

  • 工厂模式(Factory Pattern)是Java中最常用的设计模式之一
  • 这种类型的设计模式属于创建型模式,它提供了一种创建对象的方式
  • 之前我们创建类对象时,都是new对象的形式创建,除了new以外工厂模式也可以创建

工厂模式的作用

  1. 对象通过工厂的方法创建返回,工厂的方法可以为该对象进行加工和数据注入
  2. 可以实现类与类之间的解耦合操作(核心思想)

小结:

  • 优点:工厂模式的存在可以改变创建对象的方式,解决类与类之间的耦合性
  • 缺点:工厂设计模式多了一个工厂类
public abstract class Animal{
    
    
    public abstract void run();
}
public class Car extends Animal{
    
    
    @Override
    public void run(){
    
    
        System.out.println("能抓鱼");
    }
}
public class Dog extends Animal{
    
    
    @Override
    public void run(){
    
    
        System.out.println("看门");
    }
}
  • 工厂设计模式
public class FactoryPattern{
    
    
    // 不用动其他模块的代码,统一由工厂调控
    public static Animal createAnimal(){
    
    
        return new Dog();
    }
    public static Animal createAnimal1(){
    
    
        return new Cat();
    }
}
public static void main(String args[]){
    
    
    // 旧方式
    Animal a = new Cat();
    a.run();
    // 工厂模式
    Animal a = FactoryPattern.createAnimal();
    a.run();
}

装饰模式

在不改变原来类,不适用继承的基础上,动态地扩展一个类的功能

思想:创建要给新类,包装原始类,从而在新类中提升原来的功能

小结:装饰类可以在不改变原类的基础上对类中的方法进行扩展增强,实现原则为:

  1. 定义父类
  2. 定义原始类,继承父类,定义功能
  3. 定义装饰类,继承父类,包装原始类,增强功能

Commons-io包的使用

Commons-io是apache开源基金组织提供的一组有关IO操作的类库,可以提高IO功能开发的效率

  • org.apache.commons.io :有关Streams、Readers、Writes、Files的工具类
  • org.apache.commons.io.input :输入流相关的实现类,包含Reader和InputStream
  • org.apache.commons.io.output :输出流相关的实现类,包含Writer和OutputStream
  • org.apache.commons.io.serialization :序列化相关的类

步骤:

  1. 下载Commons-io相关的jar包
  2. 复制到指定的Module的lib目录中
  3. 加入到classpath中
public static void main(String args[]){
    
    
    // 使用框架复制文件
    IOUtils.copy(new FileInputStream("01_Demo/1.txt"), new FileOutputStream("01_Demo/2.txt"));
    // 使用框架文件复制到文件夹
    FileUtils.copyFileToDirectiry(new File("01_Demo/1.txt"), new File("D:/JavaTest"));
    // 使用框架文件夹复制到文件夹
    FileUtils.copyFileToDirectiry(new File("D:/zimo"), new File("D:/JavaTest"));
}

小结:IOUtils和FileUtils可以方便的复制文件和文件夹

  • JDK1.7开始sun公司自己实现了copy技术
public static void main(String args[]){
    
    
   File.copy(Paths.get("01_Demo/1.txt"), new FileOutputStream("01_Demo/2.txt"))
}

Base64

Base64是网络上最常见的用于传输8Bit字节码的编码方式之一,Base64就是一种基于64哥可打印字符来标识二进制数据的方法。

在Java 8中Base64编码已经成为Java类库的标准,Java 8 内置了Base64 编码的编码器和解码器

Base64工具类提供了一套静态方法获取下面三种Base64编解码器:

  • **基本:**输出被映射到一组字符A-Za-z0-9+/,编码不添加任何行标,输出的解码仅支持A-Za-z0-9+/。
  • **URL:**输出映射到一组字符A-Za-z0-9+/,输出是URL和文件
  • **MIME:**输出映射到MIME友好格式。输出每行不超过76字符,并且使用’\r’并跟随’\n’作为分割。编码输出最后没有行分割
/**
 *	目标:https://www.baidu.com/s?ie=utf-8&f=8&rsv_bp=1&rsv_idx=1&tn=baidu&
 *	wd=%E9%BB%91%E9%A9%AC%E7%A8%8B%E5%BA%8F%E5%91%98&rsv_pq=adb2aafb0004cea1&rsv_t=bd4
 *
 *	Base64可以实现编码和解码
 * 	Java 8 内置了Base64编码的解码器和编码器
 *	
 *	encode:编码。
 *	decode:解码。
 */
public class Base64Demo{
    
    
    public static void main(String args[]){
    
    
        try{
    
    
            // 1-1. 基本编码后结果。普通文本
            String rs = Base64.getEncoder().encodeToString("哈哈".getByte());		// 5ZOI5ZOI
            // 1-2. 基本解码后结果
            byte[] decode = Base64.getDecoder().decode(rs);
            System.out.println(new String(decode));		// 哈哈
            
            // 2-1. URL编码
            String url = Base64.getUrlEncoder().encodeToString("?login=zimo&pass=12345".getBytes());
            System.out.println(url);	// P2xvZ2luPXppbW8mcGFzcz0xMjM0NQ==
            // 2-2. URL解码
            byte[] url1 = Base64.getUrlDecoder().decode(url);
            System.out.println(new String(url1));	// ?login=zimo&pass=12345
            
            // 3-1. MIME编码(大文件,邮箱等)
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < 10; i++) {
    
    
                sb.append(UUID.randomUUID().toString());
            }
            String mime = Base64.getMimeEncoder().encodeToString(sb.toString().getBytes());
            System.out.println(mime); // M2FmMDM0ZmItM2QyMy00Y2YwLWEwMzEtMWUzNmI3ZDQ1OTgwNjAzMDk0ZjQtOTI0Yy00ZTM3LWI0
                                      // NTMtZWQ5NWQzYTdiN2FkYzg2N2YyYzctOGY1NC00ZmFjLWI2MzctOTk1NDM3YzMxYTQyMTJlZDZk
                                      // MTctYWJkMS00MTgxLWJmYjktNzg2NjM0YzkwZDIwZDMxMjcyNDItYjM2My00YjVjLWEwOGUtMzMz
                                      // ODk3Y2M5NWViZWY3NWFmYjctZmUwZC00YjNlLTk1MWItNjMzOGYwZTI2NmVlMzAzN2MxMTYtZDA3
                                      // OC00M2U0LWJkNGUtMTI2OWJkOGU1NmE1YWYyZmFhMWQtNDA0OS00MjI0LWI2MGItMGRkOTVkYjAz
                                      // NDZjODc1ZmU1OWMtODY5My00NTE4LTkwNmItOGQ2YmM0NzNhZDE2YjJiMTAyNWUtZjc4MC00MTY3
                                      // LWE3ZTEtNDNlMmFiNTFhNmQ0
            // 3-2. MIME解码
            byte[] mime1 = Base64.getMimeDecoder().decode(mime);
            System.out.println(new String(mime1));
            // 252b9219-fdfa-4151-811a-884970a9295f
            // 7e60291f-d03b-4f13-8839-9254f681a7d2
            // c5c2fe56-6e89-4eb2-80a5-c95d4ab3899f
            // ebb3651b-e3f4-4861-b9eb-0efedf00b413
            // db6b06a4-e3d4-4e9a-a67b-6aecd7435613
            // 5200e404-e0e8-4c8a-b297-55a8430c33ed
            // c06da559-eb6b-41c8-9ff7-4d9a7f431ca4
            // cda1d55b-6df3-4f61-8289-723b24c20795
            // 10f59318-571e-4bd1-a45b-cb1cd9c34bcf
            // cac21ea5-bf28-45e0-977b-cd18365363fc
        }catch(Exception e){
    
    
            
        }
    }
}

猜你喜欢

转载自blog.csdn.net/qq_38205875/article/details/109069794