XML、XML解析、设计模式等

XML、XML解析、设计模式等

XML

XML概述

XML概述
  • XML是可扩展标记语言(eXtensible Markup Language)的缩写,它是是一种数据表示格式,可以描述非常复杂的数据结构,常用于传输和存储数据。
XML的几个特点和使用场景
  • 一是纯文本,默认使用UTF-8编码;二是可嵌套;
  • 如果把XML内容存为文件,那么它就是一个XML文件。
  • XML的使用场景:XML内容经常被当成消息进行网络传输,或者作为配置文件用于存储系统的信息。
总结
  1. XML是什么?
    XML的全称为(EXtensible Markup Language),是一种可扩展的标记语言。
    它是是一种数据表示格式,可以用于自定义数据格式。
  2. XML的作用是什么?
    用于进行存储数据和传输数据
    作为软件的配置文件

XML的创建、语法规则

XML的创建
  • 就是创建一个XML类型的文件,要求文件的后缀必须使用xml,如hello_world.xml
XML的语法规则
  • XML文件的后缀名为:xml
  • 文档声明必须是第一行
<?xml version="1.0" encoding="UTF-8" ?>

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

encoding:本XML文件的编码

XML的标签(元素)规则
  • 标签由一对尖括号和合法标识符组成: ,必须存在一个根标签,有且只能有一个。
  • 标签必须成对出现,有开始,有结束:
  • 特殊的标签可以不成对,但是必须有结束标记,如:
  • 标签中可以定义属性,属性和标签名空格隔开,属性值必须用引号引起来<student id = “1">
  • 标签需要正确的嵌套
XML的其他组成
  • XML文件中可以定义注释信息:

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

  • 在这里插入图片描述

  • XML文件中可以存在CDATA区: <![CDATA[ …内容… ]]>

总结
  1. XML的组成格式要求是什么样的?
    • 文件后缀必须是xml
    • 文档声明必须是第一行
    • 必须存在一个根标签,有且只能有一个
    • XML文件中可以定义注释信息:
    • 标签必须成对出现,有开始,有结束标签:
    • 必须能够正确的嵌套

XML文档约束方式一-DTD约束[了解]

什么是文档约束

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

  • 文档约束:是用来限定xml文件中的标签以及属性应该怎么写。
文档约束的分类
  • DTD
  • schema
XML文档约束-DTD的使用(了解)

需求:利用DTD文档约束,约束一个XML文件的编写。
分析:
①:编写DTD约束文档,后缀必须是.dtd

<!ELEMENT 书架 (书+)> <!ELEMENT 书 (书名,作者,售价)> <!ELEMENT 书名 (#PCDATA)> <!ELEMENT 作者 (#PCDATA)> <!ELEMENT 售价 (#PCDATA)>

②:在需要编写的XML文件中导入该DTD约束文档
③:按照约束的规定编写XML文件的内容。

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

XML文档约束方式二-schema约束[了解]

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

需求:利用schema文档约束,约束一个XML文件的编写。
分析:
①:编写schema约束文档,后缀必须是.xsd,具体的形式到代码中观看。
②:在需要编写的XML文件中导入该schema约束文档
③:按照约束内容编写XML文件的标签。

  1. XML的文档约束-schema的优点?
    可以约束XML文件的标签内容格式,以及具体的数据类型。
    本身也是xml文件,格式更严谨。

XML解析技术

XML解析技术概述

1、XML的数据的作用是什么,最终需要怎么处理?
存储数据、做配置信息、进行数据传输。
最终需要被程序进行读取,解析里面的信息。

什么是XML解析
  • 使用程序读取XML中的数据
两种解析方式
  • SAX解析
  • DOM解析
Dom常见的解析工具
名称说明
JAXPSUN公司提供的一套XML的解析的API
JDOMJDOM是一个开源项目,它基于树型结构,利用纯JAVA的技术对XML文档实现解析、生成、序列化以及多种操作。
dom4j是JDOM的升级品,用来读写XML文件的。具有性能优异、功能强大和极其易使用的特点,它的性能超过sun公司官方的dom 技术,同时它也是一个开放源代码的软件,Hibernate也用它来读写配置文件。
jsoup功能强大DOM方式的XML解析开发包,尤其对HTML解析更加方便

在这里插入图片描述

Dom4J解析XML文件

使用Dom4J解析出XML文件

需求:使用Dom4J把一个XML文件的数据进行解析
分析:
下载Dom4j框架,官网下载。
在项目中创建一个文件夹:lib
将dom4j-2.1.1.jar文件复制到 lib 文件夹
在jar文件上点右键,选择 Add as Library -> 点击OK
在类中导包使用

Dom4j解析XML-得到Document对象

SAXReader类

构造器/方法说明
public SAXReader()创建Dom4J的解析器对象
Document read(String url)加载XML文件成为Document对象

Document类

方法名说明
Element getRootElement()获得根元素对象

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

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

方法名说明
List elements()得到当前元素下所有子元素
List elements(String name)得到当前元素下指定名字的子元素返回集合
Element element(String name)得到当前元素下指定名字的子元素,如果有很多名字相同的返回第一个
String getName()得到元素名字
String attributeValue(String name)通过属性名直接得到属性值
String elementText(子元素名)得到指定名称的子元素的文本
String getText()得到文本

Dom4J解析XML文件-案例实战

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

Dom4J的解析后的数据形式。
通常数据会封装成Java的对象,如单个对象,或者集合对象形式。

package com.itheima.d1_dom4j;

/**
 * <contact id="1" vip="true">
 *         <name>   潘金莲  </name>
 *         <gender>女</gender>
 *         <email>panpan@itcast.cn</email>
 *     </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 gendar, String email) {
        this.name = name;
        this.id = id;
        this.vip = vip;
        this.gender = gendar;
        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 +
                ", gendar=" + gender +
                ", email='" + email + '\'' +
                '}';
    }
}

package com.itheima.d1_dom4j;

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

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.List;

/**
 * 目标:学会使用dem4j解析XML文件中的数据
 * 1.导入dom4j框架
 * 2.准备一个XML文件。
 */
public class Dom4jHelloWorldDemo1 {
    @Test
    public void parseXMLData() throws Exception {
        //1.创建一个Dom4j的解析器对象,代表了整个dmo4j框架
        SAXReader saxReader=new SAXReader();
        //2.把XML文件加载到内存中成为Document文档对象
        //Document document=saxReader.read(new File("D:\\code\\javapro\\javamax\\xml-app\\src\\Contacts.xml"));//需要通过模块名去定位
        //Document document=saxReader.read(new FileInputStream("D:\\code\\javapro\\javamax\\xml-app\\src\\Contacts.xml"));
        //注意:/是直接去src下寻找的文件
        InputStream is=Dom4jHelloWorldDemo1.class.getResourceAsStream("/Contacts.xml");
        Document document=saxReader.read(is);

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

        //4.拿根元素下的全部子元素对象
        List<Element> sonEles=root.elements();
        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 idAttter= contact.attribute("id");
        System.out.println(idAttter.getName()+"-->"+idAttter.getValue());
        //直接提取属性值
        System.out.println(contact.attributeValue("id"));
        System.out.println(contact.attributeValue("vip"));
        //获取当前元素下的子元素
        Element email=contact.element("email");
        System.out.println(email.getText());
        //
    }
}

package com.itheima.d1_dom4j;

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

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

//需求:解析XML中的数据成为一个List集合对象
public class Dom4jTest2 {
    @Test
    public void parseToList() throws Exception {
        //1.导入框架(做过了)
        //2.创建SaxReader对象
        SAXReader saxReader=new SAXReader();
        //3.加载XML文件成为文档对象
        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) {
            //8.每个子元素都是一个联系人对象
            Contact contact=new Contact();
            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.elementText("email"));
            //9.把联系人对象数据加入到List集合
            contacts.add(contact);
        }
        //10.遍历List集合
        for (Contact contact : contacts) {
            System.out.println(contact);
        }
    }
}

##XML检索技术:Xpath

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

  • Dom4j需要进行文件的全部解析,然后再寻找数据。
  • Xpath技术更加适合做信息检索。
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如下:

方法名说明
Node selectSingleNode(“表达式”)获取符合表达式的唯一元素
List selectNodes(“表达式”)获取符合表达式的元素集合
Xpath的四大检索方案
  • 绝对路径
  • 相对路径
  • 全文检索
  • 属性查找
XPath:绝对路径
  • 采用绝对路径获取从根节点开始逐层的查找/contactList/contact/name节点列表并打印信息
方法名说明
/根元素/子元素/孙元素从根元素开始,一级一级向下查找,不能跨级
XPath:相对路径
  • 先得到根节点contactList
  • 再采用相对路径获取下一级contact 节点的name子节点并打印信息
方法名说明
./子元素/孙元素从当前元素开始,一级一级向下查找,不能跨级
XPath:全文搜索
  • 直接全文搜索所有的name元素并打印
方法名说明
//contact找contact元素,无论元素在哪里
//contact/name找contact,无论在哪一级,但name一定是contact的子节点
//contact//namecontact无论在哪一种,name只要是contact的子孙元素都可以找到
XPath:属性查找
  • 在全文中搜索属性,或者带属性的元素
方法名说明
//@属性名查找属性对象,无论是哪个元素,只要有这个属性即可。
//元素[@属性名]查找元素对象,全文搜索指定元素名和属性名。
//元素//[@属性名=‘值’]查找元素对象,全文搜索指定元素名和属性名,并且属性值相等。
package 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;

/**
    目标:XPath检索XML中的信息啊。(了解)

    引入:
        Dom4J可以用于解析整个XML的数据。
        但是如果要检索XML中的某些信息,建议使用XPath.(Xpath依赖Dom4j技术)
        Dom4J用于解析数据,Xpath用于检索数据。
    XPath使用步骤:
        1.导入dom4j框架。(XPath依赖于Dom4j技术,必须先导入dom4j框架!)
        2.导入XPath独有的框架包。jaxen-1.1.2.jar
    XPath常用API:
        List<Node> selectNodes(String var1):检索出一批节点集合。
        Node selectSingleNode(String var1):检索出一个节点返回。
    XPath提供的四种检索数据的写法:
        1.绝对路径。
        2.相对路径。
        3.全文搜索。
        4.属性查找。
    小结:
         1.绝对路径: /根元素/子元素/子元素。
         2.相对路径: ./子元素/子元素。 (.代表了当前元素)
         3.全文搜索:
                //元素  在全文找这个元素
                //元素1/元素2  在全文找元素1下面的一级元素2
                //元素1//元素2  在全文找元素1下面的全部元素2
         4.属性查找。
                //@属性名称  在全文检索属性对象。
                //元素[@属性名称]  在全文检索包含该属性的元素对象。
                //元素[@属性名称=值]  在全文检索包含该属性的元素且属性值为该值的元素对象。
 */
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>nameNodes =root.selectNodes("./contact/name");
        for (Node nameNode : nameNodes) {
            Element nameEle= (Element) nameNode;
            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 attribute= (Attribute) node;
            System.out.println(attribute.getName()+"==>"+attribute.getValue());
        }
        //查询name元素包含id属性的
        //Node node=document.selectSingleNode("//name[@id]");
        Node node=document.selectSingleNode("//name[@id=8]");
        Element ele= (Element) node;
        System.out.println(ele.getTextTrim());//我是西门庆
    }

}

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

设计模式:工厂模式

什么是工厂设计模式?
  • 之前我们创建类对象时, 都是使用new 对象的形式创建,在很多业务场景下也提供了不直接new的方式 。
  • 工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一, 这种类型的设计模式属于创建型模式,它提供了一种获取对象的方式。
工厂设计模式的作用:
  • 工厂的方法可以封装对象的创建细节,比如:为该对象进行加工和数据注入。
  • 可以实现类与类之间的解耦操作(核心思想)。
工厂设计模式的作用
  • 对象通过工厂的方法创建返回,工厂的方法可以为该对象进行加工和数据注入
  • 可以实现类与类之间的解耦操作(核心思想)
package d3_factory_pattern;

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

package d3_factory_pattern;


/**
    目标:工厂模式。

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

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

    小结:
        工厂模式的思想是提供一个工厂方法返回对象!
 */
public class FactoryDemo {
    public static void main(String[] args) {
        Computer c1=FactoryPattern.creatComputer("huawei");
        c1.start();
        Computer c2=FactoryPattern.creatComputer("mac");
        c2.start();
    }
}


package d3_factory_pattern;

public class FactoryPattern {
    /**
       定义一个方法,创建对象返回
     */
public static  Computer creatComputer(String info) {
    switch (info) {
        case "huawei":
            Computer c = new Huawei();
            c.setName("华为pro");
            c.setPrice(9999);
            return c;
        case "mac":
            Computer c2 = new Mac();
            c2.setName("MacBook");
            c2.setPrice(9999);
            return c2;
        default:
            return null;
    }
}
}

package d3_factory_pattern;

public class Huawei extends Computer{
    @Override
    public void start() {
        System.out.println(getName() + "开机了,展示了华为的菊花图标~~~~");
    }
}

package d3_factory_pattern;

public class Mac extends Computer{
    @Override
    public void start() {
        System.out.println(getName() + "以非常优雅的方法启动了,展示了一个苹果logo");
    }
}

设计模式:装饰模式

什么是装饰设计模式?
  • 创建一个新类,包装原始类,从而在新类中提升原来类的功能。
装饰设计模式的作用:
  • 作用:装饰模式指的是在不改变原类的基础上, 动态地扩展一个类的功能。

InputStream(抽象父类)

FileInputStream(实现子类,读写性能较差)原始类

BufferedInputStream(实现子类,装饰类,读写性能高)装饰类
设计过程说明:

  • 定义父类。
  • 定义原始类,继承父类,定义功能。
  • 定义装饰类,继承父类,包装原始类,增强功能!!
装饰设计模式的作用?

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

package d4_decorator_pattern;

/**
   装饰类:继承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);
    }
}

package d4_decorator_pattern;

/**
  装饰模式

    定义父类:InputStream
    定义实现类:FileInputStream 继续父类 定义功能
    定义装饰实现类:BufferedInputStream 继承父类 定义功能 包装原始类,增强功能。
 */
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]));
    }
}
package d4_decorator_pattern;

import java.util.Arrays;

/**
   原始类
 */
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;
    }
}

package d4_decorator_pattern;

/**
   共同父类
 */
public abstract class InputStream {
    public abstract int read();
    public abstract int read(byte[] buffer);
}

= new BufferedInputStream(new FileInputStream());
System.out.println(is.read());
System.out.println(is.read(new byte[3]));
}
}


```java
package d4_decorator_pattern;

import java.util.Arrays;

/**
   原始类
 */
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;
    }
}

package d4_decorator_pattern;

/**
   共同父类
 */
public abstract class InputStream {
    public abstract int read();
    public abstract int read(byte[] buffer);
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值