Java SE 学习笔记(十九)—— XML、设计模式

目录

  • 1 XML
    • 1.1 XML 概述
    • 1.2 XML 语法规则
    • 1.3 XML 文档约束(了解)
      • 1.3.1 DTD 约束
      • 1.3.2 schema 约束
  • 2 XML 解析
    • 2.1 XML 解析概述
    • 2.2 Dom4J 解析 XML 文件
    • 2.3 XML 解析案例
  • 3 XML 检索
  • 4 设计模式
    • 4.1 工厂模式
    • 4.2 装饰模式

1 XML


在有些业务场景下,存储数据或者传输数据给别人的时候需要满足一定的规范进行组织

1.1 XML 概述


XML 的全称为(EXtensible Markup Language),是一种 可扩展标记语言,是一种数据表示格式,可以用于自定义数据格式,可以描述非常复杂的数据结构,常用于传输和存储数据。

例如:

<?xml version="1.0" encoding="UTF-8"?>
<data><sender> 张三 </sender><receiver> 李四 </receiver><src><addr> 北京 </addr><date>2022-11-11 11:11:11</date></src><current> 武汉 </current><dest> 广州 </dest>
</data>

XML 的几个特点和使用场景

  • 一是纯文本,默认使用 UTF-8 编码;二是可嵌套;
  • 如果把 XML 内容存为文件,那么它就是一个 XML 文件。
  • XML 内容经常被 当成消息进行网络传输,或者 作为配置文件用于存储系统的信息

1.2 XML 语法规则


  1. XML 的创建

就是创建一个 XML 类型的文件,要求文件的后缀名必须使用 xml,如:helloworld.xml

  1. XML 文件的文档声明

XML 文件的文档声明必须在第一行

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

version : XML 默认的版本号码、该属性是必须存在的
encoding :本 XML 文件的编码

  1. XML 的标签 ( 元素 ) 规则
  • 标签由一对尖括号和合法标识符组成:<name></name>,必须存在一个根标签,有且只能有一个
  • 标签必须成对出现,有开始,有结束 : <name></name>
  • 特殊的标签可以不成对,但是必须有结束标记,如 :<br/>
  • 标签中可以定义属性,属性和标签名空格隔开 ,属性值必须用引号引起来 <student id = “1”></name>
  • 标签需要正确的嵌套
  • XML 文件中可以定义注释信息: <!-- 注释内容 -->
  • XML 文件中可以存在以下特殊字符
    • &lt;< 小于
    • &gt;> 大于
    • &amp;& 和号
    • &apos;' 单引号
    • &quot;" 引号
  • XML 文件可以存在 CDATA 区 (IDEA中输入CD再回车)

示例代码

<?xml version="1.0" encoding="UTF-8" ?>
<student><msg>age &gt; 18 &amp;&amp; age &lt;24<![CDATA[age>18 && age<24]]></msg>
</student>

1.3 XML 文档约束(了解)


问题:由于 XML 文件可以自定义标签,导致 XML 文件可以随意定义,程序在解析的时候可能出现问题。

文档约束是用来限定 XML 文件中的标签以及属性应该怎么写,以此强制约束程序员必须按照文档约束的规定来编写 XML 文件中

文档约束可以分为:DTD和 schema 两种

1.3.1 DTD 约束


需求:利用 DTD 文档约束,约束一个 XML 文件的编写。

分析:

  • 编写 DTD 约束文档,后缀必须是 .dtd
  • 在需要编写的 XML 文件中导入该 DTD 约束文档
  • 按照约束的规定编写 XML 文件的内容

示例代码

在这里插入图片描述

XML 的文档约束 -DTD 的作用和问题?

  • 可以约束 XML 文件的编写。
  • 不能约束具体的数据类型。

1.3.2 schema 约束


schema 可以约束具体的数据类型,约束能力上更强大,但由于其本身也是一个 XML 文件,也受到其他约束文件的要求,所以编写地更严谨

需求:利用 schema 文档约束,约束一个 XML 文件的编写。

分析:

  • 编写 schema 约束文档,后缀必须是 .xsd
  • 在需要编写的 XML 文件中导入该 schema 约束文档
  • 按照约束内容编写 XML 文件的标签。

示例代码

在这里插入图片描述

2 XML 解析

2.1 XML 解析概述


XML 的数据的作用是什么,最终需要怎么处理?

  • 存储数据、做配置信息、进行数据传输。
  • 最终需要被程序进行读取,解析里面的信息。

主要有两种解析方式: SAX 解析、DOM 解析

Dom 常见的解析工具

在这里插入图片描述

DOM 解析解析文档对象模型

在这里插入图片描述

Document 对象:整个 xml 文档
Node 对象

  • Element 对象:标签
  • Attribute 对象:属性
  • Text 对象:文本内容

2.2 Dom4J 解析 XML 文件


需求:使用 Dom4J 把一个 XML 文件的数据进行解析

分析:

  • 下载 Dom4j 框架,官网下载。
  • 在项目中创建一个文件夹: lib
  • 将 dom4j-2.1.1.jar 文件复制到 lib 文件夹
  • 在 jar 文件上点右键,选择 Add as Library -> 点击 OK
  • 在类中导包使用

Dom4j 解析 XML- 得到 Document 对象

SAXReader类

在这里插入图片描述

Document 类

在这里插入图片描述

Dom4j 解析 XML 的元素、属性、文本

在这里插入图片描述

示例代码

XML文件

<?xml version="1.0" encoding="UTF-8"?>
<contactList><contact id="1" vip="true">哈哈哈<name>   潘金莲  </name><gender></gender><email>panpan@it.cn</email></contact><contact id="2" vip="false"><name>武松</name><gender></gender><email>wusong@it.cn</email></contact><contact id="3" vip="false"><name>武大狼</name><gender></gender><email>wuda@it.cn</email></contact><user></user>
</contactList>

解析XML文件

import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.junit.Test;
import java.io.InputStream;public class Dom4jDemo {@Testpublic void parseXML() throws Exception{// 1. 创建一个Dom4j解析器对象,代表了整个Dom4j框架SAXReader saxReader = new SAXReader();// 2. 把XML文件加载到内存中称为一个Document对象
//        Document document = saxReader.read("xml\\src\\Contacts.xml");
//        Document document = saxReader.read(new File("xml\\src\\Contacts.xml"));
//        Document document = saxReader.read(new FileInputStream("xml\\src\\Contacts.xml"));// getResourceAsStream 中的/是直接去src下寻找文件InputStream is = Dom4jDemo.class.getResourceAsStream("/Contacts.xml");Document document = saxReader.read(is);// 3. 获取根元素对象Element rootElement = document.getRootElement();System.out.println(rootElement.getName()); // contactList// 4. 获取子元素// 4.1 获取根元素下所有的子元素(一级)
//        List<Element> elements = rootElement.elements();
//        for (Element element : elements) {
//            System.out.println(element.getName());
//        }// 4.2 获取某个子元素(若同名,默认提取第一个子元素对象)Element contact = rootElement.element("contact");System.out.println(contact.getName()); // contact// 4.3 获取当前元素的文本System.out.println(contact.getText());// 去掉前后空格System.out.println(contact.getTextTrim()); // 哈哈哈// 4.4 获取子元素文本System.out.println(contact.elementText("name"));// 去掉前后空格System.out.println(contact.elementTextTrim("name")); // 潘金莲// 4.5 根据元素获取属性值Attribute id = contact.attribute("id");// 打印属性名和属性值System.out.println(id.getName()+":"+id.getValue());// 4.6 直接获取属性值System.out.println(contact.attributeValue("id")); // 1System.out.println(contact.attributeValue("vip")); // true}
}

2.3 XML 解析案例


需求 : 利用 Dom4J 的知识,将 Contact.xml 文件中的联系人数据封装成 List 集合,其中每个元素是实体类 Contact 。打印输出 List 中的每个元素。

案例用到的 XML 文件见上文

创建 Contact 类

public class Contact {private String name;private int id;private boolean vip;private char gender;private String email;public Contact() {}public Contact(String name, int id, boolean vip, char gender, String email) {this.name = name;this.id = id;this.vip = vip;this.gender = gender;this.email = email;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getId() {return id;}public void setId(int id) {this.id = id;}public boolean isVip() {return vip;}public void setVip(boolean vip) {this.vip = vip;}public char getGender() {return gender;}public void setGender(char gender) {this.gender = gender;}public String getEmail() {return email;}public void setEmail(String email) {this.email = email;}@Overridepublic String toString() {return "Contact{" +"name='" + name + '\'' +", id=" + id +", vip=" + vip +", gender=" + gender +", email='" + email + '\'' +'}';}
}

解析XML

import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.junit.Test;import java.lang.invoke.StringConcatException;
import java.util.ArrayList;
import java.util.List;public class TestDemo {@Testpublic void parseToList() throws Exception {// 1. 创建saxReader对象SAXReader saxReader = new SAXReader();// 2. 加载XML文件成为Document对象Document document = saxReader.read(TestDemo.class.getResourceAsStream("/Contacts.xml"));// 3. 先获取根元素Element rootElement = document.getRootElement();// 4. 获取所有的contact子元素List<Element> contactEles = rootElement.elements("contact");// 5. 准备一个ArrayList集合封装联系人信息ArrayList<Contact> contactsList = new ArrayList<>();// 6. 遍历每一个contact子元素for (Element contactEle : contactEles) {// 7. 每一个contact子元素都是一个联系人对象Contact contact = new Contact();// 8. 提取信息并给对象赋值contact.setId(Integer.valueOf(contactEle.attributeValue("id")));contact.setVip(Boolean.valueOf(contactEle.attributeValue("vip")));contact.setName(contactEle.elementTextTrim("name"));contact.setGender(contactEle.elementTextTrim("gender").charAt(0));contact.setEmail(contactEle.elementTextTrim("email"));// 9.把联系人对象放入List集合contactsList.add(contact);}// 10. 遍历集合for (Contact contact : contactsList) {System.out.println(contact);}}
}

输出结果

在这里插入图片描述

总结

  • Dom4J 解析 XML 文件的核心思想
    • 得到文档对象 Document ,从中获取元素对象和内容。
  • Dom4J 的解析后的数据形式。
    • 通常数据会封装成 Java 的对象,如单个对象,或者集合对象形
      式。

3 XML 检索


如果需要从 XML 文件中检索需要的某个信息(如 name )怎么解决?

  • Dom4j 需要进行文件的全部解析,然后再寻找数据。
  • Xpath 技术更加适合做信息检索。

XPath 在解析 XML 文档方面提供了一独树一帜的路径思想,更加优雅,高效。XPath 使用路径表达式来定位 XML 文档中的元素节点或属性节点。

使用 Xpath 检索出 XML 文件

需求:使用 Dom4J 把一个 XML 文件的数据进行解析

分析:

  • 导入 jar 包 (dom4j 和 jaxen-1.1.2.jar) , Xpath 技术依赖 Dom4j 技术
  • 通过 dom4j 的 SAXReader 获取 Document 对象
  • 利用 XPath 提供的 API, 结合 XPath 的语法完成选取 XML 文档元素节点进行解析操作。

Document 中与 Xpath 相关的 API

在这里插入图片描述

Xpath 的四大检索方案

  1. 绝对路径:采用绝对路径获取从根节点开始逐层的查找 /contactList/contact/name 节点列表并打印信息

在这里插入图片描述

  1. 相对路径:先得到根节点 contactList,再采用相对路径获取下一级 contact 节点的 name 子节点并打印信息

在这里插入图片描述

  1. 全文检索:直接全文搜索所有的 name 元素并打印

在这里插入图片描述

  1. 属性查找:在全文中搜索属性,或者带属性的元素

在这里插入图片描述

示例代码

XML文件

<?xml version="1.0" encoding="UTF-8"?>
<contactList><contact id="1" vip="true"><name>   潘金莲  </name><gender></gender><email>panpan@itcast.cn</email></contact><contact id="2" vip="false"><name>武松</name><gender></gender><email>wusong@itcast.cn</email></contact><contact id="3" vip="false"><name>武大狼</name><gender></gender><email>wuda@itcast.cn</email></contact><user><contact><info><name id="666">西门庆</name></info></contact></user>
</contactList>

检索XML

import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;
import org.junit.Test;import java.util.List;public class XPathDemo {// 1. 绝对路径@Testpublic void parse01() throws Exception {// 创建解析器对象SAXReader saxReader = new SAXReader();// 将XML文件加载成Document对象Document document = saxReader.read(XPathDemo.class.getResourceAsStream("/Contacts2.xml"));// 检索全部名称:name值List<Node> nodes = document.selectNodes("/contactList/contact/name");for (Node node : nodes) {Element nameEle = (Element) node;System.out.println(nameEle.getTextTrim());}}// 2. 相对路径@Testpublic void parse02() throws Exception {// 创建解析器对象SAXReader saxReader = new SAXReader();// 将XML文件加载成Document对象Document document = saxReader.read(XPathDemo.class.getResourceAsStream("/Contacts2.xml"));Element rootElement = document.getRootElement();// 检索全部名称:name值List<Node> nodes = rootElement.selectNodes("./contact/name");for (Node node : nodes) {Element nameEle = (Element) node;System.out.println(nameEle.getTextTrim());}}// 3. 全文搜素@Testpublic void parse03() throws Exception {// 创建解析器对象SAXReader saxReader = new SAXReader();// 将XML文件加载成Document对象Document document = saxReader.read(XPathDemo.class.getResourceAsStream("/Contacts2.xml"));// 检索数据
//        List<Node> nodes = document.selectNodes("//name");// 会找"西门庆"
//        List<Node> nodes = document.selectNodes("//contact/name");// 不会找"西门庆"List<Node> nodes = document.selectNodes("//contact//name");// 会找"西门庆"for (Node node : nodes) {Element nameEle = (Element) node;System.out.println(nameEle.getTextTrim());}}// 4. 属性查找@Testpublic void parse04() throws Exception {// 创建解析器对象SAXReader saxReader = new SAXReader();// 将XML文件加载成Document对象Document document = saxReader.read(XPathDemo.class.getResourceAsStream("/Contacts2.xml"));// 检索数据// 在全文中检索属性对象List<Node> nodes = document.selectNodes("//@id");for (Node node : nodes) {Attribute attr = (Attribute) node;System.out.println(attr.getName()+":"+attr.getValue());}// 在全文中检索包含该属性的元素对象(若有多个只返回第一个)// 查询name元素(包含id属性的)
//        Node node = document.selectSingleNode("//name[@id]");// 在全文中检索属性对象且属性值为该值的元素对象Node node = document.selectSingleNode("//name[@id=666]");Element ele = (Element) node;System.out.println(ele.getTextTrim());}
}

Element和继承Node

4 设计模式

4.1 工厂模式


之前我们创建类对象时,都是使用 new 对象的形式创建,在很多业务场景下也提供了不直接 new 的方式 。

工厂模式( Factory Pattern )是 Java 中最常用的设计模式之一, 这种类型的设计模式属于创建型模式,它提供了一种获取对象的方式。

工厂设计模式的作用:

  • 工厂的方法可以封装对象的创建细节,比如:为该对象进行加工和数据注入。
  • 可以实现类与类之间的解耦操作(核心思想)

4.2 装饰模式


装饰设计模式:创建一个新类,包装原始类,从而在新类中提升原来类的功能。

装饰设计模式的作用:

  • 装饰模式指的是在不改变原类的基础上 ,动态地扩展一个类的功能

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/123697.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2022年上半年上午易错题(软件设计师考试)

1.以下关于冯诺依曼计算机的叙述中&#xff0c;不正确的是( )。 A.程序指令和数据都采用二进制表示 B.程序指令总是存储在主存中&#xff0c;而数据则存储在高速缓存中 C.程序的功能都由中央处理器(CPU)执行指令来实现 D.程序的执行过程由指令进行自动控制 程序指令和数据…

力扣第738题 单调递增的数字 c++ 暴力超时 贪心优化

题目 738. 单调递增的数字 中等 相关标签 贪心 数学 当且仅当每个相邻位数上的数字 x 和 y 满足 x < y 时&#xff0c;我们称这个整数是单调递增的。 给定一个整数 n &#xff0c;返回 小于或等于 n 的最大数字&#xff0c;且数字呈 单调递增 。 示例 1: 输入: n 1…

ZYNQ连载03-Vivado创建工程

ZYNQ连载03-Vivado创建工程 1. 硬件参数 名称参数主控xc7z020clg400-2DDRMT41J256M16RE-125 2. 创建工程 3. 串口配置 4. DDR配置 5. SD配置 6. ETH配置 7. USB配置 8. 导出硬件 Generate Output ProductsCreate HDL WrapperExport Hardware Platform 执行以上步骤后&#…

leetCode 76. 最小覆盖子串 + 滑动窗口 + 哈希Hash

我的往期文章&#xff1a;此题的其他解法&#xff0c;感兴趣的话可以移步看一下&#xff1a; leetCode 76. 最小覆盖子串 滑动窗口 图解&#xff08;详细&#xff09;-CSDN博客https://blog.csdn.net/weixin_41987016/article/details/134042115?spm1001.2014.3001.5501 力…

【软件安装环境配置】VsCode安装和配置各种环境(保姆级)

一、VsCode 下载 1.官网下载 网站&#xff1a;Visual Studio Code - Code Editing. Redefined 打开网站 点击Download 根据操作系统&#xff08;macOS、Windows、Linux&#xff09;和版本下载 下载到本地 注意&#xff1a; 若下载很慢&#xff0c;或者下着下着就暂停了 可…

【设计模式】第15节:行为型模式之“职责链模式”

一、简介 职责链模式&#xff1a;将请求的发送和接收解耦&#xff0c;让多个接收对象都有机会处理这个请求。将这些接收对象串成一条链&#xff0c;并沿着这条链传递这个请求&#xff0c;直到链上的某个接收对象能够处理它为止。 二、优点 分离发送者和接受者易于扩展和维护…

【已解决】VSCode运行C#控制台乱码显示

问题描述 如上图所示&#xff0c;最近在学习C#突然发现我在运行Hello World的时候出现这样的乱码情况。 分析原因 主要是因为VS Code 是UTF-8的编码格式&#xff0c;而我们的PC是Unicode编码&#xff0c;所以我们需要对其进行一个统一即可解决问题。那么知道这个的问题那就开…

【Docker】如何查看之前docker run命令启动的参数

个人主页&#xff1a;金鳞踏雨 个人简介&#xff1a;大家好&#xff0c;我是金鳞&#xff0c;一个初出茅庐的Java小白 目前状况&#xff1a;22届普通本科毕业生&#xff0c;几经波折了&#xff0c;现在任职于一家国内大型知名日化公司&#xff0c;从事Java开发工作 我的博客&am…

H5游戏源码分享-密室逃脱小游戏(考验反应能力)

H5游戏源码分享-密室逃脱小游戏&#xff08;考验反应能力&#xff09; 预判安全位置&#xff0c;这个需要快速的反应能力 源码 <!DOCTYPE html> <html> <head> <meta http-equiv"Content-Type" content"text/html; charsetutf-8" /&…

1.spark standalone环境安装

概述 环境是spark 3.2.4 hadoop版本 3.2.4&#xff0c;所以官网下载的包为 spark-3.2.4-bin-hadoop3.2.tgz 在具体安装部署之前&#xff0c;需要先下载Spark的安装包&#xff0c;进到 spark的官网&#xff0c;点击download按钮 使用Spark的时候一般都是需要和Hadoop交互的&a…

10_4阻塞和非阻塞跟poll和等待队列

阻塞和非阻塞 广泛上的区别就是 应用程序如果非阻塞那读取不到数据就应该马上有返回值 阻塞的话就是在应用程序去read数据,但是设备驱动没有数据,就一直卡住,直到有数据再继续往下 补充阻塞知识,应用层大部分都是阻塞 如果要非阻塞 ,应用程序在打开设备节点的时候填写int fd …

辅助驾驶功能开发-功能规范篇(22)-4-L2级辅助驾驶方案功能规范

1.3.4 LDW系统功能定义 1.3.4.1 状态机 1.3.4.2 功能定义 1.3.4.2.1 信号需求列表 1.3.4.2.2 系统开启关闭 1)初始化 车辆上电后,车道偏离预警系统(LDW)进行初始化,控制器需要在上电后 220ms 内发出第一帧报文,并在 3s 内 完成内部自检,同时上电 3s 内不进行关联系统…

ActiveMQ

ActiveMQ 安装 下载网址&#xff1a;ActiveMQ 一定要和自己安装的jdk版本匹配&#xff0c;不然会报错 下载到本地之后解压缩 有可能端口号被占用 解除端口号占用&#xff0c;参考&#xff1a;Windows_端口被占用 打开cmd 查询所有的端口号 netstat -nao查询指定端口号 n…

数组元素逆序交换

数组元素逆序交换 例如&#xff1a; 输入&#xff1a; 1,2,3,4,5 输出&#xff1a; 5,4,3,2,1 代码&#xff1a; #include<stdio.h> #define N 5 int main() {int a[N], i, temp;for (i 0; i < N; i) {scanf("%d", &a[i]);}for (i 0; i < N…

C语言选择排序

1.选择排序(Selection sort) 选择排序是简单直观的排序算法。 基本思想&#xff1a;从首元素开始&#xff0c;首元素与它后面的所有元素进行比较&#xff0c;找到数列中最小的元素&#xff0c;与首元素值交换。然后下一个元素与它后面的元素比较&#xff0c;得到第二小的元素…

对Linux线程的理解(什么是线程,线程的创建终止等待分离,线程互斥,Linux常见的锁,线程同步),两万字总结,有这一篇文章就够了!

文章目录 一、什么是线程1.线程是怎样描述的2.线程与进程的区别3.线程的优缺点4.理解Linux的轻量级进程 二、Linux线程控制1.线程创建:pthread_create()2.线程终止:pthread_exit()3.线程等待:pthread_join()4.分离线程:pthread_detach() 三、Linux线程互斥1.互斥量2.线程安全与…

我在Vscode学OpenCV 初步接触

OpenCV是一个开源的计算机视觉库&#xff0c;可以处理图像和视频数据。它包含了超过2500个优化过的算法&#xff0c;用于对图像和视频进行处理&#xff0c;包括目标识别、面部识别、运动跟踪、立体视觉等。OpenCV支持多种编程语言&#xff0c;包括C、Python、Java等&#xff0c…

在HTML当中引入Vue控件,以element-ui为例

前情&#xff1a;需要实现一个同时满足按天、按周、按月选择的时间选择器&#xff0c;但是以HTML为基础写的都不太满足我的要求&#xff0c;要么只能按天选择&#xff0c;要么就是想选择久远的时间得点很久&#xff0c;除非自己写捷径&#xff0c;所以就看上了element-ui的这个…

动静分离技术

一、HAproxy 动静分离 1、概念&#xff1a; HAproxy 动静分离技术是一种用于优化 Web 服务器性能和提高用户体验的策略&#xff0c;它通过将动态内容和静态内容分别路由到不同的后端服务器来实现&#xff0c;减轻服务器负载&#xff0c;提高网站的响应速度。 动态内容包括由…

SylixOS BSP开发(七)

实现系统调试信息打印接口 当系统出错时或者使用内核日志时会输出一些打印信息&#xff0c;这最终都是调用到bspLib.c中的bspDebugMsg 这个接口来实现的&#xff0c;所以我们在开发BSP时&#xff0c;第一个要做的工作就是实现这个接口。 一般的调试信息都是通过串口来输出的&am…