学习日记(XML 文件解析、检索、工厂设计模式、装饰设计模式)

学习日记(XML 文件解析、检索、工厂设计模式、装饰设计模式)

一、XML 概述

1. 概念

XML:可扩展标记语言 eXtensible Markup Language 的缩写,是一种数据表示格式,可以描述非常复杂的数据结构,常用于传输和存储数据。如果把 XML 内容存为文件,那么该文件就是 XML 文件。

特点:纯文本,默认使用 UTF-8 编码;可嵌套。

作用:用于进行存储数据和传输数据;作为配置文件用于存储系统的信息。

2. XML 的创建及语法规则

创建:创建一个 XML 类型的文件,文件的后缀名为 .xml,如:hello_world.xml

XML 的标签(元素)语法规则

  • 文档声明必须是第一行;
  • 标签由一对尖括号和合法标识符组成,必须存在一个根标签,有且只能有一个
  • 标签必须成对出现,有开始,有结束,结束的标签有 / 标记;
  • 特殊的标签可以不成对,但是必须有结束标记,如:<br/>
  • 标签中可以定义属性,属性和标签名空格分开,属性值必须用引号引起来;
  • 标签需要正确的嵌套
  • 定义注释信息可以用:<!-- 注释内容 -->
  • 可以存在 CDATA 区:<![CDATA[ 内容 ]]>,其中可以写任何内容,快捷键CD
  • 如果存在特殊字符可以用以下替代
替代特殊字符
&lt;< 小于
&gt;> 大于
&amp;& 和号
&apos;‘ 单引号
&quot;“ 引号

右键点击文件选择 Open in Browser,用浏览器打开显示如下

3. XML 文档约束方式

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

XML 文档约束方式分为:DTD 约束和 schema 约束。

依据文档约束来编写 XML 文档的步骤

  • 在需要编写的 XML 文件中导入 DTD 或 schema 约束文档;
  • 按照约束的规定编写 XML 文件的内容。

注意

  • DTD 约束文档后缀为 .dtd;schema 约束文档也是一个 XML 文件,后缀为 .xsd

  • DTD 不能约束具体的数据类型;schema 可以约束具体的数据类型。


二、XML 文件的解析技术

XML 文件解析:使用程序读取 XML 文件中的数据。

两种解析方式:SAX 解析和 DOM 解析(解析常用的技术框架:Dom4j)。

DOM 解析文档对象模型:

  • Document 对象代表整个 XML 文档;
  • Element 对象代表标签(元素);
  • Attribute 对象代表属性;
  • Text 对象代表文本内容。

注意Element 对象、Attribute 对象以及 Text 对象都实现了 Node 接口,都是节点类型(最高类型)。


1. 使用 Dom4j 解析 XML 文件

首先需要在官网下载 Dom4j 框架,然后导入 jar 包。

解析的步骤

  • 导入 Dom4j 框架;
  • 通过构造器创建一个 Dom4j 的解析器对象,代表整个 Dom4j 框架,如:SAXReader saxReader = new SAXReader();
  • 利用解析器对象调用 read 方法把 XML 文件加载到内存中成为一个 Document 文档对象;
  • 通过 Document 文档对象调用 getRootElement 方法来获取根元素对象;
  • 通过根元素对象调用以下各种方法获取子元素对象、属性对象、文本等。

方法名说明
List elements()得到当前元素下所有子元素对象
Element element(String var1)得到当前元素下指定名字子元素对象返回集合
List attributes()得到当前元素下的所有属性对象
Attribute attribute(String var1)得到当前元素下指定属性名属性对象
String getText()得到当前元素下的文本,返回值为 String 类型
String getTextTrim()得到当前元素下的文本(去掉前后空格),返回值为 String 类型

注意

  • 在第二个方法中,若参数中指定的名字对应不止一个子元素对象,则默认提取第一个子元素对象。
  • 获取到子元素对象后,可以继续调用 getName 方法和 getText 方法获取元素的名字和文本。
  • 获取到属性对象后,可以继续调用 getName 方法和 getValue 方法获取属性的名称和对应的值。
  • 获取子元素对象后可以继续调用 elements 方法,进一步获取子元素的子元素对象。
  • API 很灵活,用到时再去查

解析结果

注意

  • 最好使用 Class 对象调用 getResourceAsStream 来产生字节输入流,这样可以避免后续模块名发生改变而可能出现的错误。
  • getResourceAsStream 方法中的 / 可以直接去 src 下寻找文件,而且必须是正斜杠
  • 先获取元素对象或属性对象,然后再进行进一步操作。

2. XML 解析案例

需求:将指定 XML 文件中的数据封装为 List 集合,其中每个元素是实体类 Contact

实现

运行结果

注意:获取属性值或子元素对象文本有两种方法:先获取属性对象或子元素对象,然后调用方法;也可以直接调用以下方法获取。

方法名说明
String attributeValue(String var1)直接获取元素的属性值
String elementTextTrim(String var1)直接获取该元素下子元素的文本(去掉前后空格)

代码

package com.dom4j;

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

import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

public class Demo02 {

    public static void main(String[] args) throws Exception {

        SAXReader saxReader = new SAXReader();

        InputStream is = Demo02.class.getResourceAsStream("/XMLdata/data01.xml");
        Document document = saxReader.read(is);

        List<Contact> list = Demo02.praseToList(document);
        System.out.println(list);

    }


    public static List<Contact> praseToList(Document document) {
        // 定义一个 list 集合用于存储 Contact 对象
        List<Contact> list = new ArrayList<>();

        Element root = document.getRootElement();

        // 根元素的子元素
        List<Element> elements = root.elements("contact");

        // 遍历根元素的子元素
        for (Element element : elements) {
            // 每有一个子元素,就创建一个 Contact 对象
            Contact con = new Contact();

            // 子元素的属性对象值
            con.setId(Integer.valueOf(element.attributeValue("id")));
            con.setVip(Boolean.valueOf(element.attributeValue("vip")));

            con.setName(element.elementTextTrim("name"));
            con.setAge(Integer.valueOf(element.elementTextTrim("age")));
            con.setHobby(element.elementTextTrim("hobby"));
//            // 取子元素的子元素对象
//            List<Element> elems = element.elements();
//            for (Element elem : elems) {
//                switch (elem.getName()) {
//                    case "name":
//                        con.setName(elem.getTextTrim());
//                        break;
//                    case "age":
//                        con.setAge(Integer.valueOf(elem.getTextTrim()));
//                        break;
//                    case "hobby":
//                        con.setHobby(elem.getTextTrim());
//                        break;
//                    default:
//                        break;
//                }
//            }
            list.add(con);
        }
        return list;
    }
}

三、XML 文件的数据检索技术:XPath

XPath 作用:检索 XML 文件中的信息。

XPath 使用路径表达式来定位 XML 文档中的元素节点或属性节点。

检索的步骤

  • 导入 Dom4j 框架和 XPath 的 jar 包(XPath 技术依赖于 Dom4j 技术);
  • 通过构造器创建一个 Dom4j 的解析器对象,如:SAXReader saxReader = new SAXReader();
  • 利用解析器对象调用 read 方法把 XML 文件加载到内存中成为一个 Document 文档对象;
  • 利用 XPath 提供的以下 API,结合路径表达式来完成检索 XML 文档中的元素节点属性节点
方法名说明
Node selectSingleNode(String var1)获取符合路径表达式的唯一元素
List selectNodes(String var1)获取符合路径表达式的元素集合
元素查找的路径表达式说明
/根元素/子元素/子元素绝对路径
./子元素/子元素相对路径,其中 . 表示当前元素
//元素在全文搜索全部这个元素
//元素1/元素2在全文元素 1 下找一级元素 2
//元素1//元素2在全文元素 1 下找全部元素 2

注意/ 表示一级元素// 表示全部元素

根据属性查找属性对象或元素对象的路径表达式说明
//@属性名查找所有属性对象
//元素[@属性名]查找带有指定属性名的元素对象
//元素//[@属性名 = '值']查找带有指定属性名,并且属性值相等的元素对象

注意:路径表达式都是正斜杠 /

元素查找

属性查找或元素查找


四、工厂设计模式

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

作用

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


五、装饰设计模式

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

步骤

  • 定义父类;
  • 定义原始类,继承父类,定义功能;
  • 定义装饰类,继承父类包装原始类,增强功能。

作用:在不改变原类的基础上,动态地扩展一个类的功能。

如:InputStream 是抽象父类,FileInputStream 是实现子类、BufferedInputStream 是实现子类,是装饰类,读写性能提高。

实践:模拟 IO 流。

注意:在 main 方法中,is 的实际类型为 FileInputStream,所以在使用构造器创建 bis 对象时,传入的参数实际类型为 FileInputStream,之后在装饰类调用 read 方法时,调用的是原始类(实现类)中的 read 方法(多态特点)。


注意:

  1. Dom4j 框架和 XPath 的 jar 包下载链接:点此下载,提取码:3285。
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Sun 3285

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

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

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

打赏作者

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

抵扣说明:

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

余额充值