JavaSE——XML、解析、设计模式

XML

XML概述

  • XML是可拓展标记语言(extensible Markup Language)的缩写,他是一种数据表示格式,可以描述非常复杂的数据结构,常用于传输和存储数据。
<?xml version="1.0"	encoding="UTF-8"?>
<data>
    <sender>张三</sender>
    <receiver>李四</receiver>
    <src>
    		<addr>北京</addr>
    		<date>2022-01-29 11:11:11</date>
    </src>
    <current>武汉</current>
    <dest>广州</dest>
</data>

XML的几个特点和使用场景

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

XML的创建、语法规则

XML的创建

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

IDEA创建XML文件的步骤

XML的语法规则

  • XML文件的后缀名为:xml
  • 文档声明必须是第一行

XML的标签(元素)规则

  • 标签由一对尖括号和合法标识符组成:,必须存在一个根标签,有且只能有一个。
  • 标签必须成对出现有开始有结束;
  • 特殊的标签可以不成对,但是必须有结束标记,如:
  • 标签中可以定义属性,属性和标签名空格隔开,属性值必须用引号引起来
  • 标签需要正确的嵌套

XMl的其他组成

XML文档约束方式一、DTD约束

什么是文档约束?

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

文档约束的分类

  • DTD

data.dtd
    <!ELEMENT 书架 (+)>
    <!ELEMENT 书 (书名,作者,售价)>
    <!ELEMENT 书名 (#PCDATA)>
    <!ELEMENT 作者 (#PCDATA)>
    <!ELEMENT 售价 (#PCDATA)>
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE 书架 SYSTEM "data.dtd">
<书架>
    <>
        <书名>JavaSE</书名>
        <作者>cs</作者>
        <售价>122</售价>
    </>
    <>
        <书名>bb</书名>
        <作者>aa</作者>
        <售价>一百</售价>
    </>
</书架>

小结

  1. XML的文档约束-DTD的作用和问题?
    1. 可以约束xml文件的编写
    2. 不能约束具体的数据类型
  • schema

文档的约束方式二-schema约束

文档约束-schema

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

XML解析技术

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

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

XML解析技术概述

什么是XML解析

  • 使用程序读取XML中的数据

两种解析方式

  • SAX解析
  • DOM解析

Dom常见的解析工具

DOM解析解析文档对象模型

Dom4J解析XML文件

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

分析:

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

Dom4J解析XML得到Document对象

Contacts.xml
<?xml version="1.0" encoding="UTF-8" ?>
<contactList>
    <contact id="1" vip="true">
        <name>潘金莲</name>
        <gender></gender>
        <email>panpan@163.com.cn</email>
    </contact>
    <contact id="2" vip="false">
        <name>武松</name>
        <gender></gender>
        <email>wus@qq.com</email>
    </contact>
</contactList>
/**
 使用dom4j解析xml文件中的数据
 1.导入dom4j框架
 2.准备一个XML文件
 */
public class Dom4JHelloWorldDemo1 {
    @Test
    public void parseXMLData() throws Exception {
        //1.创建一个Dom4J解析器对象,代表整个dom4j框架
        SAXReader saxReader = new SAXReader();
        //2.把XMl文件加载到内存中称为一个Document文档对象
//        Document document = saxReader.read(new File("xml-app\\xmldata\\helle_world_dtd.xml"));
//        Document document = saxReader.read(new FileInputStream("xml-app\\\\xmldata\\\\helle_world_dtd.xml"));

        //注意:/是直接去src下寻找的文件
        InputStream is = Dom4JHelloWorldDemo1.class.getResourceAsStream("/Contacts.xml");
        Document document = saxReader.read(is);

        //3.获取根元素对象
        Element element = document.getRootElement();
        System.out.println(element.getName());
    }
}
output:
contactList

Dom4J解析XML文件中的各种节点

Dom4J解析XMl的元素、属性、文本

/**
 * 使用dom4j解析xml文件中的数据
 * 1.导入dom4j框架
 * 2.准备一个XML文件
 */
public class Dom4JHelloWorldDemo1 {
    @Test
    public void parseXMLData() throws Exception {
        //1.创建一个Dom4J解析器对象,代表整个dom4j框架
        SAXReader saxReader = new SAXReader();
        //2.把XMl文件加载到内存中称为一个Document文档对象
//        Document document = saxReader.read(new File("xml-app\\xmldata\\helle_world_dtd.xml"));
//        Document document = saxReader.read(new FileInputStream("xml-app\\\\xmldata\\\\helle_world_dtd.xml"));

        //注意:/是直接去src下寻找的文件
        InputStream is = Dom4JHelloWorldDemo1.class.getResourceAsStream("/Contacts.xml");
        Document document = saxReader.read(is);

        //3.获取根元素对象
        Element root = document.getRootElement();
        System.out.println(root.getName());

        //4.拿根元素下面的全部子元素对象(一级)
//        List<Element> sonEles = root.elements();
        List<Element> sonEles = root.elements("contact");
        for (Element sonEle : sonEles) {
            System.out.println(sonEle.getName());
        }

        //拿某个子元素
        Element userEle = root.element("user");
        System.out.println(userEle.getName());

        //默认提取第一个子元素对象
        Element contact = root.element("contact");
        System.out.println(contact.elementText("name"));
        //去掉前后空格
        System.out.println(contact.elementTextTrim("name"));
        //根据元素获取属性值
        Attribute idAddr = contact.attribute("id");
        System.out.println(idAddr.getName() + "-->" + idAddr.getValue());
        //直接提取属性值
        System.out.println(contact.attributeValue("id"));
        System.out.println(contact.attributeValue("vip"));
        //获取当前元素下的子元素对象
        Element email = contact.element("email");
        System.out.println(email.getText());
    }
}
output:
contactList
contact
contact
user
  潘金莲  
潘金莲
id-->1
1
true
panpan@163.com.cn

Dom4J解析XML文件-案例实战

Contacts.xml

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

Contact.java

package com.csl.d1_dom4j;

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;
    }

    @Override
    public String toString() {
        return "Contact{" +
                "name='" + name + '\'' +
                ", id=" + id +
                ", vip=" + vip +
                ", gender=" + gender +
                ", email='" + email + '\'' +
                '}';
    }
}

Dom4jTest2

package com.csl.d1_dom4j;

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

import java.util.ArrayList;
import java.util.List;

public class Dom4jTest2 {
    @Test
    public void parseToList() throws Exception {
        //需求:解析XML中的数据成为一个List集合对象
        //1.导入框架
        //2.创建SaxReader对象
        SAXReader saxReader = new SAXReader();
        //3.加载XML文件成为文档对象Document对象
        Document document =
                saxReader.read(Dom4jTest2.class.getResourceAsStream("/Contacts.xml"));
        //4.先拿根元素
        Element root = document.getRootElement();
        //5.提取contact子元素
        List<Element> contactEles = root.elements("contact");
        //6.准备一个ArrayList集合封装联系人信息
        List<Contact> contacts = new ArrayList<>();
        //7.遍历Contact子元素
        for (Element contactEle : contactEles) {
            //每个子元素都是一个联系人对象
            Contact contact = new Contact();
            contact.setId(Integer.valueOf(contactEle.attributeValue("id")));
            contact.setVip(Boolean.valueOf(contactEle.attributeValue("vip")));
            contact.setName(contactEle.elementTextTrim("name"));
            contact.setEmail(contactEle.elementText("email"));
            contact.setGender(contactEle.elementTextTrim("gender").charAt(0));
            //9.把联系人对象数据加入到List集合中
            contacts.add(contact);
        }
        //10.遍历List集合
        for (Contact contact : contacts) {
            System.out.println(contact);
        }
    }
}
output:
Contact{name='潘金莲', id=1, vip=true, gender=, email='panpan@163.com.cn'}
Contact{name='武松', id=2, vip=false, gender=, email='wus@qq.com'}
Contact{name='武大朗', id=3, vip=false, gender=, email='wuda@qq.com'}

XML检索技术:Xpath

Xpath介绍

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

示例:

  • /元素/子元素/孙元素

使用Xpath检索出XML文件

Xpath的四大检索方案

  • 绝对路径
  • 相对路径
  • 全文检索
  • 属性查找

Xpath:绝对路径

  • 采用绝对路径获取从根节点开始逐层的查找/contactList/contact/name节点列表并打印信息
方法名说明
/根元素/子元素/孙元素从根元素开始,一级一级向下查找,不能跨级

Xpath:绝对路径

  • 采用绝对路径获取从根节点开始逐层的查找/contactList/contact/name节点列表并打印信息
方法名说明
/根元素/子元素/孙元素从根元素开始,一级一级向下查找,不能跨级

Contacts2.xml

<?xml version="1.0" encoding="UTF-8" ?>
<contactList>
    <contact id="1" vip="true">
        <name>潘金莲</name>
        <gender></gender>
        <email>panpan@163.com.cn</email>
    </contact>
    <contact id="2" vip="false">
        <name>武松</name>
        <gender></gender>
        <email>wus@qq.com</email>
    </contact>
    <contact id="3" vip="false">
        <name>武大朗</name>
        <gender id="444"></gender>
        <email>wuda@qq.com</email>
    </contact>
    <user>
        <info>
            <contact>
                <name id="666">我是西门庆</name>
            </contact>
        </info>
    </user>
</contactList>
package com.csl.d2_xpath;

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.绝对路径:/根元素/子元素/孙元素
     */
    @Test
    public void parse01() throws Exception{
        //a.创建解析器对象
        SAXReader saxReader = new SAXReader();
        //b.把XML文件加载成Document文档对象
        Document document =
                saxReader.read(XPathDemo.class.getResourceAsStream("/Contacts2.xml"));
        //c.检索全部的名称
        List<Node> nameNodes = document.selectNodes("/contactList/contact/name");
        for (Node nameNode : nameNodes) {
            Element nameEle = (Element) nameNode;
            System.out.println(nameEle.getTextTrim());
        }
    }

    /**
     2.相对路径:    ./子元素/子元素(.代表了当前元素)
     */
    @Test
    public void parse02()throws Exception{
        //a.创建解析器对象
        SAXReader saxReader = new SAXReader();
        //b.加载XMl文件成Document文档对象
        Document document = saxReader.read(XPathDemo.class.getResourceAsStream("/Contacts2.xml"));
        Element root = document.getRootElement();
        //c.通过根元素来检索全部的节点
        List<Node> nodes = root.selectNodes("./contact/name");
        for (Node node : nodes) {
            Element nameEle = (Element) node;
            System.out.println(nameEle.getTextTrim());
        }
    }

    /**
     3.全文检索:
     //元素   在全文查找这个元素
     //元素1/元素2  在全文找元素1下面的一级元素2
     //元素1//元素2     在全文找元素1下面的全部元素2
     */
    @Test
    public void parse03()throws Exception{
        //a.创建解析器对象
        SAXReader saxReader = new SAXReader();
        //b.加载XML文件成Document文档对象
        Document document = saxReader.read(XPathDemo.class.getResourceAsStream("/Contacts2.xml"));
        //c.检索数据
//        List<Node> nameNodes = document.selectNodes("//name");
//        List<Node> nameNodes = document.selectNodes("//contact/name");
        List<Node> nameNodes = document.selectNodes("//contact//name");
        for (Node nameNode : nameNodes) {
            Element nameEle = (Element) nameNode;
            System.out.println(nameEle.getTextTrim());
        }
    }

    /**
     4.属性查找:
     //@属性名称    在全文检索属性对象
     //元素[@属性名称]    在全文检索包含该属性的元素对象
     //元素[@属性名称=值]  在全文检索包含该属性的元素且属性值为该值的元素对象
     */
    @Test
    public void parse04()throws Exception{
        //a.创建解析器对象
        SAXReader saxReader = new SAXReader();
        //b.把XML加载成Document文档对象
        Document document =
                saxReader.read(XPathDemo.class.getResourceAsStream("/Contacts2.xml"));
        //c.检索数据
        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());
    }
}
output:
1.
潘金莲
武松
武大朗
2.
潘金莲
武松
武大朗
3.
潘金莲
武松
武大朗
我是西门庆
4.
id===>1
id===>2
id===>3
id===>444
id===>666
我是西门庆

小结:

  1. Xpath作用,四大类。
  • 检索XML文件中的信息
  • 绝对路径:/根元素/子元素/孙元素
  • 相对路径:./子元素/孙元素
  • 全文检索://contact
  • 属性查找://@属性名、//元素[@属性名]、//元素//[@属性名=‘值’]

设计模式:工厂模式

什么是工厂设计模式?

  • 之前我们创建类对象时,都是使用new对象的形式创建,在很多业务场景下也提供了不直接new的方式
  • 工厂模式(Factory Pattern)是Java中最常见的设计模式之一,这种类型的设计模式属于创建型模式,它提供了一种获取对象的方式。
public abstract class Computer {
    private String name;
    private double price;

   public abstract void start();

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }
}
public class Mac extends Computer{

    @Override
    public void start() {
        System.out.println(getName()+"苹果电脑启动了~~~~");
    }
}
public class Huawei extends Computer {

    @Override
    public void start() {
        System.out.println(getName() + "huawei电脑启动了~~~~");
    }
}
public class FactoryPattern {
    /**
        定义一个方法,创建对象返回
     */
    public static Computer creatComputer(String info){
        switch (info){
            case "Mac":
                Computer c1 = new Mac();
                c1.setName("苹果电脑");
                c1.setPrice(11999);
                return c1;
            case "Huawei":
                Computer c2 = new Huawei();
                c2.setName("华为电脑");
                c2.setPrice(9999);
                return c2;
            default:
                return null;
        }
    }
}
public class FactoryDemo {
    public static void main(String[] args) {
        Computer c1 = FactoryPattern.creatComputer("Huawei");
        c1.start();

        Computer c2 = FactoryPattern.creatComputer("Mac");
        c2.start();
    }
}
output:
华为电脑huawei电脑启动了~~~~
苹果电脑苹果电脑启动了~~~~

工厂设计模式的作用

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

设计模式:装饰模式

什么是装饰设计模式?

  • 创建一个新类,包装原始类,从而在新类中提升原来类的功能。

装饰设计模式的作用:

  • 作用:装饰模式指的是在不改变原类的基础上,动态地拓展一个类的功能。
InputStream(抽象父类)
FileInputStream(实现子类,读写性能较差)
BufferedInputStream(实现子类,装饰类,读写性能高)
  1. 定义父类
  2. 定义原始类,继承父类,定义功能。
  3. 定义装饰类,继承父类,包装原始类,增强功能!!
/**
    共同父类
 */
public abstract class InputStream {
    public abstract int read();
    public abstract int read(byte[] buffer);
}
public class FileInputStream extends InputStream{
    @Override
    public int read() {
        System.out.println("低性能的方式读了一个字节a");
        return 97;
    }

    @Override
    public int read(byte[] buffer) {
        buffer[0] = 97;
        buffer[1] = 98;
        buffer[2] = 99;
        System.out.println("低性能的方式读了一个字节数组"+ Arrays.toString(buffer));
        return 3;
    }
}
/**
 * 装饰类,继承InputStream,拓展原始类的功能
 */
public class BufferedInputStream extends InputStream {
    private InputStream is;
    public BufferedInputStream(InputStream is) {
        this.is=is;
    }

    @Override
    public int read() {
        System.out.println("提供8KB的缓冲区,提高读写性能~");
        return is.read();
    }

    @Override
    public int read(byte[] buffer) {
        System.out.println("提供8KB的缓冲区,提高读写性能~");
        return is.read(buffer);
    }
}
public class DecoratorPattern {
    public static void main(String[] args) {
        InputStream is = new BufferedInputStream(new FileInputStream());
        System.out.println(is.read());
        System.out.println(is.read(new byte[3]));
    }
}
output:
提供8KB的缓冲区,提高读写性能~
低性能的方式读了一个字节a
97
提供8KB的缓冲区,提高读写性能~
低性能的方式读了一个字节数组[97, 98, 99]
3
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值