1.XML

1.1、XML概述

  • XML是可扩展标记语言(eXtensible Markup Language)的缩写,它是一种数据表示格式,可以描述非常复杂的数据结构,常用于传输和存储数据
<?xml version="1.0" encoding="utf-8" ?>
<student>
    <name>浩楠</name>
    <age>22</age>
    <address>河南</address>
    <info>
        <school>洛阳理工</school>
        <phone>158...</phone>
    </info>
</student>
  • XML的几个特点和使用场景
    • 纯文本,默认使用UTF-的编码,还可以嵌套
    • 如果吧XML内容存为问及那,那么它就是一个XML文件
    • XML的使用场景:XML内容经常被当成消息进行网络传播,或者作为配置文件用于存储系统的信息

1.2、XML的创建、语法规则

  • 创建
    • 创建后缀为xml的即为xml文件

image-20230810164027626.png

  • 语法规则
    • xml文件的后缀名为:xml
    • 文档声明必须是第一行
<?xml version="1.0" encoding="UTF-8">
version:XML默认的版本号码、该属性是必须存在的
encoding:XML文件的编码
  • XML的标签(元素)规则

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

    • XML文件中可以定义注释信息:

    • XML文件中可以存在特殊字符

image-20230810164034718.png

  • XML文件中可以存在CDATA区:<![CDATA[内容]]>
<!-- 注释 -->
<mysql>
    <sql>
        select * from emp where age &lt; 18;
        select * from emp where age &lt 18 &amp;&amp; age > 12;
    </sql>
</mysql>

1.3、XML文档约束方式—DTD约束【了解】

  • 由于XML文件可以自定义标签,导致XML文件可以随意定义,程序在解析的时候可能出现问题,由此产生文档约束来指定规则
  • 文档约束
    • 用来限制XML文件中的标签以及属性应该怎么写
  • 案例
    • 需求:利用DTD文档约束,约束一个XML文件的编写
  • 约束文件
<!ELEMENT 书架 (书+)>
<!ELEMENT 书 (书名,作者,售价)>
<!ELEMENT 书名 (#PCDATA)>
<!ELEMENT 作者 (#PCDATA)>
<!ELEMENT 售价 (#PCDATA)>
  • xml文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE 书架 SYSTEM "data.dtd">
<书架>
    <>
        <书名></书名>
        <作者></作者>
        <售价></售价>
    </>
</书架>

【可以约束XML文件的编写,但是不能约束具体的数据类型】

1.4、XML文档约束方式二—schema约束【了解】

  • schema
    • schema可以约束具体的数据类型,约束能力上更强大
    • schema本身也是一个xml文件,本身也受到其他约束文件的需求,所以别写的更加严谨
  • 案例
    • 需求:利用schema文档约束,约束一个xml文件的编写
  • schema约束文件
<?xml version="1.0" encoding="UTF-8" ?>
<schema xmlns="http://www.w3.org/2001/XMLSchema"
        targetNamespace="http://www.itcast.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
<?xml version="1.0" encoding="UTF-8" ?>
<书架 xmlns="http://www.itcast.cn"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.itcast.cn data.xsd">
    <!-- xmlns="http://www.itcast.cn"  基本位置
         xsi:schemaLocation="http://www.itcast.cn books02.xsd" 具体的位置 -->
    <>
        <书名>神雕侠侣</书名>
        <作者>金庸</作者>
        <售价>399.9</售价>
    </>
    <>
        <书名>神雕侠侣</书名>
        <作者>金庸</作者>
        <售价>19.5</售价>
    </>

</书架>

2.XML解析技术

2.1、概述

使用程序读取XML中的数据

  • 两种解析方式
    • SAX解析
    • DOM解析
  • Dom常见的解析工具

image-20230810164047673.png

2.2、Dom4j解析XML文件

  • 案例
    • 需求:使用Dom4J吧一个XML文件的数据进行解析

image-20230810164056385.png

  • SAXReader类

image-20230810164102339.png

  • Document类

image-20230810164107367.png

  • Dom4J解析XML的元素、属性、文本

image-20230810164116717.png

  • 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>
    </user>
</contactList>
  • 运行
public class Dom4jDemo {
    public static void main(String[] args) throws Exception {
        //1.创建一个Dom4j的解析器对象,代表了整个dom4j框架
        SAXReader saxReader = new SAXReader();
        //2.吧xml文件加载到内存中成为一个document文档对象
        //Document document = saxReader.read(new File("Java\\src\\Contacts.xml"));当模块改名字以后,这里就会找不到文件
        //getResourceAsStream中的/直接去src下寻找文件
        InputStream is = Dom4jDemo.class.getResourceAsStream("/Contacts.xml");
        Document document = saxReader.read(is);
        //3.获取根元素对象
        Element root = document.getRootElement();
        System.out.println(root.getName());

        //4.拿根元素下的全部子元素(一级)
        //List<Element> elements = root.elements();
        List<Element> elements = root.elements("contact");//指定
        for (Element element : elements) {
            System.out.println(element.getName());
        }
        //指定拿单个子元素
        Element user = root.element("user");
        System.out.println(user.getName());

        System.out.println("---------------------");
        //默认获取第一个子元素对象
        Element contact = root.element("contact");
        //获取子元素文本对象
        System.out.println(contact.elementText("name"));
        //去除两边空格
        System.out.println(contact.elementTextTrim("name"));

        //根据元素获取属性值
        Attribute idAttr = contact.attribute("id");
        System.out.println(idAttr.getName()+"--->"+idAttr.getValue());
        //获取当前元素下的子元素对象,通过对象来输出值和对象的名称
        Element email = contact.element("email");
        System.out.println(email.getName()+"---->"+email.getText());

        System.out.println("--------------直接获取属性值------------");
        System.out.println(contact.attributeValue("id"));
        System.out.println(contact.attributeValue("vip"));
    }
}

2.3、案例

  • 需求:利用Dom4J的知识,讲xml文件中的联系人数据封装成list集合,并打印输出

  • xml数据文件同上

  • Person【封装是实体类】
public class Person {
    private String name;
    private String sex;
    private String email;
    private Integer id;
    private boolean vip;

    public Person(String name, String sex, String email, Integer id, boolean vip) {
        this.name = name;
        this.sex = sex;
        this.email = email;
        this.id = id;
        this.vip = vip;
    }

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

    public String getName() {
        return name;
    }

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

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public Person() {
    }
}
  • Test
public class Demo {
    public static void main(String[] args) throws Exception {
        //创建SaxReader对象
        SAXReader saxReader = new SAXReader();
        InputStream is = Demo.class.getResourceAsStream("/Contacts.xml");
        //加载XML文件为document对象
        Document document = saxReader.read(is);
        //获取根元素
        Element root = document.getRootElement();
        //获取所有contact子元素
        List<Element> elements = root.elements("contact");
        List<Person> people = new ArrayList<>();
        //遍历封装为对象
        for (Element element : elements) {
            String name = element.elementTextTrim("name");
            String gender = element.elementText("gender");
            String email = element.elementText("email");
            String id = element.attributeValue("id");
            String vip = element.attributeValue("vip");
            people.add(new Person(name,gender,email,Integer.valueOf(id),Boolean.valueOf(vip)));
        }
        people.forEach(p -> {
            System.out.println(p);
        });
    }
}

3.XML检索技术:XPath

  • XPath介绍

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

image-20230810164131708.png

【检索示例文件】

<?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="111">我是西门庆</name>
            </info>
         </contact>
    </user>
</contactList>
  • Xpath的四大检索方案

    • 绝对路径:采用绝对路径获取从根节点开始逐层的茶盏/contactList/contact/name节点列表并大印信息

image-20230810164138747.png

  //1.绝对路径:/根元素/子元素/孙元素
  @Test
  public void parseXml() throws Exception {
      //a.获取解析对象
      SAXReader saxReader = new SAXReader();
      //b.读取XML文件,获取Document对象
      Document document = saxReader.read(XpathDemo.class.getResourceAsStream("/Contacts2.xml"));
      //c.搜搜全部的名称:name
      List<Node> nodes = document.selectNodes("/contactList/contact/name");
      for (Node node : nodes) {
          Element elem = (Element) node;
          System.out.println(elem.getTextTrim());
      }
  }
  • 相对路径
    • 先得到根节点contactList
    • 再采用相对路径获取下一级contact节点的name子节点并打印输出

image-20230810164144887.png

  //2.相对路径 ./子元素/孙元素 (.代表了当前元素)
  @Test
  public void parseXml02() throws Exception{
      //a.获取解析对象
      SAXReader saxReader = new SAXReader();
      //b.读取XML文件,获取Document对象
      Document document = saxReader.read(XpathDemo.class.getResourceAsStream("/Contacts2.xml"));
      //获取根元素
      Element root = document.getRootElement();
      //c.搜搜全部的名称:name
      List<Node> nodes = root.selectNodes("./contact/name");
      for (Node node : nodes) {
          Element elem = (Element) node;
          System.out.println(elem.getTextTrim());
      }
  }
  • 全文检索
    • 直接全文搜搜所有的name元素并大印

image-20230810164152584.png

  /*
      3.全文检索
      //元素 在全文找找个元素
      //元素1/元素2  在全文找元素1下面的一级元素2
      //元素1//元素2 在全文找元素1下面的全部元素2
   */
  @Test
  public void parseXml03() 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("//name");
      for (Node node : nodes) {
          Element ele = (Element) node;
          System.out.println(ele.getTextTrim());
      }
  }
  • 属性查找
    • 在全文中搜索属性,或者带有属性的元素

image-20230810202112349.png

  /*
          4.属性查找
          //@属性名称 在全文检索属性对象
          //元素【@属性名称】  在全文检索包含该属性的元素对象
          //元素【@属性名称=值】 在全文检索包含属性的元素对象且属性值为该值的元素对象
       */
  @Test
  public void paseXml04() 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 attri = (Attribute) node;
          System.out.println(attri.getName()+"===>"+attri.getValue());
      }

      //查询name元素(包含id属性的)
      //Node node = document.selectSingleNode("//name[@id]");
      Node node = document.selectSingleNode("//name[@id=111]");
      Element ele = (Element) node;
      System.out.println(ele.getTextTrim());
  }

4.设计模式:工厂模式

  • 概述
    • 之前创建类对象时,都是使用new对象的形式创建,在很多业务场景下也提供了不直接new的方式
    • 工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一,这种类型的设计模式属于创建型模式,它提供了一种获取对象的方式
  • 工厂设计模式的作用
    • 工厂的方法可以封装对象的创建细节,比如:为该对象进行加工和数据注入
    • 可以实现类于类之间的解耦操作(核心思想)
  • Computer
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 Computer(String name, double price) {
        this.name = name;
        this.price = price;
    }

    public Computer() {
    }
}
  • Mac
public class Mac extends Computer{
    @Override
    public void start() {
        System.out.println("mac启动开机!");
    }
}
  • HuaWei
public class HuaWei extends Computer{
    @Override
    public void start() {
        System.out.println("HuaWei启动开机!");
    }
}
  • FactoryPattern
public class FactoryPattern {
    public static Computer getComputer(String name){
        Computer computer;
        switch(name){
            case "mac":
                computer = new Mac();
                return computer;
            case "huawei":
                computer = new HuaWei();
                return computer;
            default:
                return null;
        }
    }
}
  • 运行
public class Demo {
    public static void main(String[] args) {
        Computer mac = FactoryPattern.getComputer("mac");
        mac.start();
        Computer huawei = FactoryPattern.getComputer("huawei");
        huawei.start();
    }
}

5.设计模式:装饰模式

  • 概述
    • 创建一个新类,包装原始类,从而在新类中提升原来类的功能
  • 装饰设计模式的作用

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

public abstract class InputStream {
    public abstract int read();
    public abstract int read(byte[] buffer);
}
  • FileInputStream(实现子类,读性能未优化)
public class FileInputStream extends InputStream{
    @Override
    public int read() {
        System.out.println("低效率读取一个字节");
        return 97;
    }

    @Override
    public int read(byte[] buffer) {
        System.out.println("低效率读取字节数组");
        return 0;
    }
}
  • BufferedInputStream
public class BufferedInputStream extends InputStream{
    private InputStream is;
    public BufferedInputStream() {
    }
    public BufferedInputStream(InputStream is){
        this.is = is;
    }

    @Override
    public int read() {
        System.out.println("创建缓冲区,高效读取字节");
        return is.read();
    }

    @Override
    public int read(byte[] buffer) {
        System.out.println("创建换成去,高效读取字节数组");
        return is.read(buffer);
    }
}
  • 运行
public class Demo {
    public static void main(String[] args) {
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream());
        bis.read();
        byte[] buffer = new byte[3];
        bis.read(buffer);
    }
}

results matching ""

    No results matching ""