目录
XML
XML概述
XML的创建、语法规则
XML文档约束方式一-DTD约束[了解]
XML文档约束方式二-schema约束[了解]
XML解析技术
XML解析技术概述
Dom4J解析XML文件
Dom4J解析XML文件中的各种节点
Dom4J解析XML文件-案例实战
XML检索技术:Xpath
设计模式:工厂模式
设计模式:装饰模式
XML是可扩展标记语言(eXtensible Markup Language)的缩写,它是是一种数据表示格式,
可以描述非常复杂的数据结构,常用于传输和存储数据。
XML的几个特点和使用场景一是纯文本,默认使用UTF-8编码;二是可嵌套;如果把XML内容存为文件,那么它就是一个XML文件。XML的使用场景:XML内容经常被当成消息进行网络传输,或者作为配置文件用于存储系统的信息。
总结
XML是什么?XML的全称为(EXtensible Markup Language),是一种可扩展的标记语言。它是是一种数据表示格式,可以用于自定义数据格式。
XML的作用是什么?用于进行存储数据和传输数据作为软件的配置文件
XML的创建
就是创建一个XML类型的文件,要求文件的后缀必须使用xml,如hello_world.xml
IDEA创建XML文件的操作步骤
XML的语法规则XML文件的后缀名为:xml文档声明必须是第一行
XML的标签(元素)规则
标签由一对尖括号和合法标识符组成: ,必须存在一个根标签,有且只能有一个。
标签必须成对出现,有开始,有结束:
特殊的标签可以不成对,但是必须有结束标记,如:
标签中可以定义属性,属性和标签名空格隔开,属性值必须用引号引起来
标签需要正确的嵌套
XML的其他组成
XML文件中可以定义注释信息:
XML文件中可以存在以下特殊字符:< < 小于> > 大于& & 和号' ' 单引号" " 引号
XML文件中可以存在CDATA区:
女儿国国王 女 唐僧 30 女儿国 select * from user where age < 18;select * from user where age < 18 && age > 10
总结
XML的组成格式要求是什么样的?文件后缀必须是xml文档声明必须是第一行必须存在一个根标签,有且只能有一个XML文件中可以定义注释信息:标签必须成对出现,有开始,有结束标签: 必须能够正确的嵌套
什么是文档约束?
问题:由于XML文件可以自定义标签,导致XML文件可以随意定义,程序在解析的时候可能出现问题。
文档约束的分类
DTD
schema
XML文档约束-DTD的使用(了解)
需求:利用DTD文档约束,约束一个XML文件的编写。
分析:
①:编写DTD约束文档,后缀必须是.dtd
②:在需要编写的XML文件中导入该DTD约束文档
③:按照约束的规定编写XML文件的内容。
<书架><书><书名>《活着》书名><作者>余华作者><售价>49.9售价>书><书><书名>《Java开发》书名><作者>地雷作者><售价>59.9售价>书>
书架>
总结
XML的文档约束-DTD的作用和问题?可以约束XML文件的编写。不能约束具体的数据类型。
文档约束-schema
schema可以约束具体的数据类型,约束能力上更强大。
schema本身也是一个xml文件,本身也受到其他约束文件的要求,所以编写的更加严谨
<书架 xmlns="bao"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="bao data.xsd"><书><书名>神雕侠侣书名><作者>金庸作者><售价>399.9售价>书><书><书名>神雕侠侣书名><作者>金庸作者><售价>19.5售价>书>书架>
1、XML的数据的作用是什么,最终需要怎么处理?
存储数据、做配置信息、进行数据传输。
最终需要被程序进行读取,解析里面的信息。
2、什么是XML解析?
使用程序读取XML中的数据
两种解析方式
SAX解析
DOM解析
Dom常见的解析工具
名称 | 说明 |
JAXP | SUN公司提供的一套XML的解析的API |
JDOM | JDOM是一个开源项目,它基于树型结构,利用纯JAVA的技术对XML文档实现解析、生成、序列化以及多种操作。 |
dom4j | 是JDOM的升级品,用来读写XML文件的。具有性能优异、功能强大和极其易使用的特点,它的性能超过sun公司官方的dom 技术,同时它也是一个开放源代码的软件,Hibernate也用它来读写配置文件。 |
jsoup | 功能强大DOM方式的XML解析开发包,尤其对HTML解析更加方便 |
DOM解析解析文档对象模型
使用Dom4J解析出XML文件
需求:使用Dom4J把一个XML文件的数据进行解析
分析:
下载Dom4j框架,官网下载。
在项目中创建一个文件夹:lib
将dom4j-2.1.1.jar文件复制到 lib 文件夹
在jar文件上点右键,选择 Add as Library -> 点击OK
在类中导包使用
Dom4j解析XML-得到Document对象
构造器/方法 | 说明 |
public SAXReader() | 创建Dom4J的解析器对象 |
Document read(String url) | 加载XML文件成为Document对象 |
方法名 | 说明 |
Element getRootElement() | 获得根元素对象 |
Dom4j解析XML的元素、属性、文本
方法名 | 说明 |
List | 得到当前元素下所有子元素 |
List | 得到当前元素下指定名字的子元素返回集合 |
Element element(String name) | 得到当前元素下指定名字的子元素,如果有很多名字相同的返回第一个 |
String getName() | 得到元素名字 |
String attributeValue(String name) | 通过属性名直接得到属性值 |
String elementText(子元素名) | 得到指定名称的子元素的文本 |
String getText() | 得到文本 |
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;/**目标:学会使用dom4j解析XML文件中的数据。1、导入dom4j框架。2、准备一个XML文件。*/
public class Dom4JHelloWorldDemo1 {@Testpublic void parseXMLData() throws Exception {// 1、创建一个Dom4j的解析器对象,代表了整个dom4j框架SAXReader saxReader = new SAXReader();// 2、把XML文件加载到内存中成为一个Document文档对象// Document document = saxReader.read(new File("xml-app\\src\\Contacts.xml")); // 需要通过模块名去定位// Document document = saxReader.read(new FileInputStream("xml-app\\src\\Contacts.xml"));// 注意: getResourceAsStream中的/是直接去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 sonEles = root.elements();List sonEles = root.elements("contact");for (Element sonEle : sonEles) {System.out.println(sonEle.getName());}// 拿某个子元素Element userEle = root.element("user");System.out.println(userEle.getName());// 默认提取第一个子元素对象 (Java语言。)Element contact = root.element("contact");// 获取子元素文本System.out.println(contact.elementText("name"));// 去掉前后空格System.out.println(contact.elementTextTrim("name"));// 获取当前元素下的子元素对象Element email = contact.element("email");System.out.println(email.getText());// 去掉前后空格System.out.println(email.getTextTrim());// 根据元素获取属性值Attribute idAttr = contact.attribute("id");System.out.println(idAttr.getName() + "-->" + idAttr.getValue());// 直接提取属性值System.out.println(contact.attributeValue("id"));System.out.println(contact.attributeValue("vip"));}
}
潘金莲 女 panpan@qq.com 武松 男 wusong@qq.com 武大狼 男 wuda@qq.com 我是西门庆
XML解析案例
需求:利用Dom4J的知识,将Contact.xml文件中的联系人数据封装成List集合,
其中每个元素是实体类Contact。打印输出 List 中的每个元素。
/** 潘金莲 女 panpan@itcast.cn */
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;}@Overridepublic String toString() {return "Contact{" +"name='" + name + '\'' +", id=" + id +", vip=" + vip +", gendar=" + gender +", email='" + email + '\'' +'}';}
}
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;public class Dom4JTest2 {@Testpublic 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 contactEles = root.elements("contact");// 6、准备一个ArrayList集合封装联系人信息List 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文件中检索需要的某个信息(如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 | 获取符合表达式的元素集合 |
Xpath的四大检索方案
绝对路径:采用绝对路径获取从根节点开始逐层的查找/contactList/contact/name节点列表并打印信息
相对路径:先得到根节点contactList再采用相对路径获取下一级contact 节点的name子节点并打印信息
全文检索:直接全文搜索所有的name元素并打印
属性查找:在全文中搜索属性,或者带属性的元素
1、Xpath作用,四大类。
检索XML文件中的信息
绝对路径: /根元素/子元素/孙元素
相对路径:./子元素/孙元素
全文检索://contact
属性查找://@属性名 、//元素[@属性名]、//元素//[@属性名=‘值’]
方法名 | 说明 |
/根元素/子元素/孙元素 | 从根元素开始,一级一级向下查找,不能跨级 |
方法名 | 说明 |
./子元素/孙元素 | 从当前元素开始,一级一级向下查找,不能跨级 |
方法名 | 说明 |
//contact | 找contact元素,无论元素在哪里 |
//contact/name | 找contact,无论在哪一级,但name一定是contact的子节点 |
//contact//name | contact无论在哪一种,name只要是contact的子孙元素都可以找到 |
方法名 | 说明 |
//@属性名 | 查找属性对象,无论是哪个元素,只要有这个属性即可。 |
//元素[@属性名] | 查找元素对象,全文搜索指定元素名和属性名。 |
//元素//[@属性名=‘值’] | 查找元素对象,全文搜索指定元素名和属性名,并且属性值相等。 |
package com.itheima.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.jarXPath常用API:List selectNodes(String var1):检索出一批节点集合。Node selectSingleNode(String var1):检索出一个节点返回。XPath提供的四种检索数据的写法:1.绝对路径。2.相对路径。3.全文搜索。4.属性查找。小结:1.绝对路径: /根元素/子元素/子元素。2.相对路径: ./子元素/子元素。 (.代表了当前元素)3.全文搜索://元素 在全文找这个元素//元素1/元素2 在全文找元素1下面的一级元素2//元素1//元素2 在全文找元素1下面的全部元素24.属性查找。//@属性名称 在全文检索属性对象。//元素[@属性名称] 在全文检索包含该属性的元素对象。//元素[@属性名称=值] 在全文检索包含该属性的元素且属性值为该值的元素对象。*/
public class XPathDemo {/**1.绝对路径: /根元素/子元素/子元素。*/@Testpublic void parse01() throws Exception {// a、创建解析器对象SAXReader saxReader = new SAXReader();// b、把XML加载成Document文档对象Document document =saxReader.read(XPathDemo.class.getResourceAsStream("/Contacts2.xml"));// c、检索全部的名称List nameNodes = document.selectNodes("/contactList/contact/name");for (Node nameNode : nameNodes) {Element nameEle = (Element) nameNode;System.out.println(nameEle.getTextTrim());}}/**2.相对路径: ./子元素/子元素。 (.代表了当前元素)*/@Testpublic 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 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*/@Testpublic void parse03() throws Exception {// a、创建解析器对象SAXReader saxReader = new SAXReader();// b、把XML加载成Document文档对象Document document =saxReader.read(XPathDemo.class.getResourceAsStream("/Contacts2.xml"));// c、检索数据//List nameNodes = document.selectNodes("//name");// List nameNodes = document.selectNodes("//contact/name");List nameNodes = document.selectNodes("//contact//name");for (Node nameNode : nameNodes) {Element nameEle = (Element) nameNode;System.out.println(nameEle.getTextTrim());}}/**4.属性查找。//@属性名称 在全文检索属性对象。//元素[@属性名称] 在全文检索包含该属性的元素对象。//元素[@属性名称=值] 在全文检索包含该属性的元素且属性值为该值的元素对象。*/@Testpublic void parse04() throws Exception {// a、创建解析器对象SAXReader saxReader = new SAXReader();// b、把XML加载成Document文档对象Document document =saxReader.read(XPathDemo.class.getResourceAsStream("/Contacts2.xml"));// c、检索数据List 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=888]");Element ele = (Element) node;System.out.println(ele.getTextTrim());}
}
什么是工厂设计模式?
之前我们创建类对象时, 都是使用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{@Overridepublic void start() {System.out.println(getName() + "以非常优雅的方法启动了,展示了一个苹果logo");}
}
public class Huawei extends Computer{@Overridepublic void start() {System.out.println(getName() + "开机了,展示了华为的菊花图标~~~~");}
}
public class FactoryPattern {/**定义一个方法,创建对象返回*/public static Computer createComputer(String info){switch (info){case "huawei":Computer c = new Huawei();c.setName("huawei pro 16");c.setPrice(5999);return c;case "mac":Computer c2 = new Mac();c2.setName("MacBook pro");c2.setPrice(11999);return c2;default:return null;}}
}
/**目标:工厂模式。什么是工厂设计模式?工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的方式。之前我们创建类对象时, 都是使用new 对象的形式创建, 除new 对象方式以外,工厂模式也可以创建对象。工厂设计模式的作用:1.对象通过工厂的方法创建返回,工厂的方法可以为该对象进行加工和数据注入。2.可以实现类与类之间的解耦操作(核心思想,重点)小结:工厂模式的思想是提供一个工厂方法返回对象!*/
public class FactoryDemo {public static void main(String[] args) {Computer c1 = FactoryPattern.createComputer("huawei");c1.start();Computer c2 = FactoryPattern.createComputer("mac");c2.start();}
}
什么是装饰设计模式?
创建一个新类,包装原始类,从而在新类中提升原来类的功能。
装饰设计模式的作用:
作用:装饰模式指的是在不改变原类的基础上, 动态地扩展一个类的功能。
设计过程说明:
定义父类。
定义原始类,继承父类,定义功能。
定义装饰类,继承父类,包装原始类,增强功能!!
/**共同父类*/
public abstract class InputStream {public abstract int read();public abstract int read(byte[] buffer);
}
import java.util.Arrays;/**原始类*/
public class FileInputStream extends InputStream{@Overridepublic int read() {System.out.println("低性能的方式读取了一个字节a");return 97;}@Overridepublic int read(byte[] buffer) {buffer[0] = 97;buffer[1] = 98;buffer[2] = 99;System.out.println("低性能的方式读取了一个字节数组:" + Arrays.toString(buffer));return 3;}
}
/**装饰模式定义父类: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]));}
}
/**装饰类:继承InputStream 拓展原始类的功能*/
public class BufferedInputStream extends InputStream{private InputStream is;public BufferedInputStream(InputStream is){this.is = is;}@Overridepublic int read() {System.out.println("提供8KB的缓冲区,提高读数据性能~~~~");return is.read();}@Overridepublic int read(byte[] buffer) {System.out.println("提供8KB的缓冲区,提高读数据性能~~~~");return is.read(buffer);}
}