Java SE基础知识详解第[20]期—XML、XML解析、设计模式

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
简介: Java SE基础知识详解第[20]期—XML、XML解析、设计模式

XML、XML解析、设计模式

1.XML

1.1XML概述

XML概述

XML是可扩展标记语言(eXtensible Markup Language)的缩写,它是是一种数据表示格式,可以用于自定义数据格式,描述非常复杂的数据结构,常用于传输和存储数据。

XML示例如下图所示。

XML_Example.png

XML的几个特点和使用场景

①纯文本,默认使用UTF-8编码,可嵌套;

②如果把XML内容存为文件,那么它就是一个XML文件;

③XML的使用场景:XML内容经常被当成消息进行网络传输,或者作为配置文件用于存储系统的配置信息

1.2XML的创建、语法规则

XML的创建

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

XML的语法规则

XML文件的后缀名为:xml

文档声明必须是第一行

如<?xmversion="1.0" encoding="UTF-8" ?>

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

encoding:本XML文件的编码。

XML的标签(元素)规则

标签由一对尖括号和合法标识符组成:<name></name>,必须存在一个根标签,有且只能有一个

标签必须成对出现,有开始,有结束:<name></name>

特殊的标签可以不成对,但是必须有结束标记,如:<br/>

标签中可以定义属性,属性和标签名空格隔开,属性值必须用双引号引起来<student id = “1”></name>

标签需要正确的嵌套

XML的其他组成

XML文件中可以定义注释信息:<!– 注释内容 -->

XML文件中某些需要替代的特殊字符

字符

替代值

含义

<

<

小于

>

>

大于

&

&

'

'

单引号

"

"

双引号

 

XML文件中可以存在CDATA区<![CDATA[ …内容… ]]>,里面的内容可以随意填写,无需使用字符替代某些特殊字符,IDEA中的快捷键CD

1.3XML文档约束方式

什么是文档约束?

由于XML文件可以自定义标签,导致XML文件可以随意定义,程序在解析的时候可能出现问题。文档约束是用来限定xml文件中的标签以及属性应该怎么写,以此强制约束程序员必须按照文档约束的规定来编写xml文件

文档约束的分类:DTD、schema

使用文档约束的步骤

①:编写schema约束文档,后缀必须是.xsd(编写DTD约束文档,后缀必须是.dtd),具体的形式到代码中观看。

②:在需要编写的XML文件中导入该schema(DTD)约束文档

③:按照约束内容编写XML文件的标签。

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

2.XML解析技术

2.1XML解析技术概述

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

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

什么是XML解析

使用程序读取XML中的数据

两种解析方式:SAX解析、DOM解析

DOM解析解析文档对象模型图示如下图所示。

DOM.png

其中,整个xml文档称为Document对象;Element对象代表标签(图示蓝色区域);Attribute对象代表属性(图示紫色区域);Text对象代表文本内容(图示黄色区域),且后三者均实现了Node接口。

Dom解析常用框架:Dom4j:把文件一次性加载到内存中,加载为Document对象再操作。

2.2Dom4J解析XML文件

Dom4J的解析思想?

得到文档对象Document,从中获取元素对象和内容。

导入Dom4J框架步骤

① 下载Dom4j框架,官网下载。 ② 在项目中创建一个文件夹:lib ③ 将dom4j-2.1.1.jar文件复制到 lib 文件夹④ 在jar文件上点右键,选择 Add as Library -> 点击OK ⑤ 在类中导包使用

Dom4j解析XML-得到Document对象

SAXReader类构造器

方法名

说明

public SAXReader()

创建Dom4J的解析器对象

 

SAXReader类得到Document的方法

方法名

说明

Document read(String url)

加载XML文件成为Document对象

 

Document得到根元素的方法

方法名

说明

Element getRootElement()

获得根元素对象

 

各级元素的方法

方法名

说明

List<Element> elements()

得到当前元素下所有下一级子元素

List<Element> elements(String name)

得到当前元素下指定名字的子元素返回集合

Element element(String name)

得到当前元素下指定名字的子元素

如果有很多名字相同的返回第一个

String getName()

得到元素名字

String attributeValue(String name)

通过属性名如果有直接得到属性值

String elementText(子元素名)

得到指定名称的子元素

此子元素只有文本,不含有子元素的文本

String getText()

得到此元素只有文本,不含有子元素文本

 

示例代码如下:

publicclassDom4JHelloWorld {
@TestpublicvoidparseXMLData() throwsException {
// 1.创建一个Dom4j的解析器对象,代表整个dom4j框架SAXReadersaxReader=newSAXReader();
// 2.把XML文件加载到内存中称为一个Document文档对象//        Document document = saxReader.read(new File("day15_xml_app\\src\\Contacts.xml"));// 此种通过File对象寻找的方式的缺点:需要通过模块名寻找,一旦模块名被修改,会找不到// getResourceAsStream中的"/"是直接去src下寻找文件InputStreamis=Dom4JHelloWorld.class.getResourceAsStream("/Contacts.xml");
// 通过此种方式找到文件字节输入流,再传递给read方法,即使模块名修改,不影响找到该xml文件Documentdocument=saxReader.read(is);
// 获取根元素Elementroot=document.getRootElement();
System.out.println(root.getName()); // contactList    }
}

注:getResourceAsStream中的"/"是直接去src下寻找文件不受模块改名的影响。如InputStream is = Dom4JHelloWorld.class.getResourceAsStream("/Contacts.xml");

XML解析案例

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

示例代码如下:

Contact.xml

<?xmversion="1.0" encoding="UTF-8"?><contactList><contactid="1"vip="true"><name>   潘金莲  </name><gender></gender><email>panpan@itcast.cn</email></contact><contactid="2"vip="false"><name>武松</name><gender></gender><email>wusong@itcast.cn</email></contact><contactid="3"vip="false"><name>武大狼</name><gender></gender><email>wuda@itcast.cn</email></contact><user></user></contactList>

Contact类

publicclassContact {
privateintid;
privatebooleanvip;
privateStringname;
privatecharsex;
privateStringemail;
publicContact() {
    }
publicContact(intid, booleanvip, Stringname, charsex, Stringemail) {
this.id=id;
this.vip=vip;
this.name=name;
this.sex=sex;
this.emai=email;
    }
publicintgetId() {
returnid;
    }
publicvoidsetId(intid) {
this.id=id;
    }
publicbooleanisVip() {
returnvip;
    }
publicvoidsetVip(booleanvip) {
this.vip=vip;
    }
publicStringgetName() {
returnname;
    }
publicvoidsetName(Stringname) {
this.name=name;
    }
publicchargetSex() {
returnsex;
    }
publicvoidsetSex(charsex) {
this.sex=sex;
    }
publicStringgetEmail() {
returnemail;
    }
publicvoidsetEmail(Stringemail) {
this.emai=email;
    }
@OverridepublicStringtoString() {
return"Contact{"+"id="+id+", vip="+vip+", name='"+name+'\''+", sex="+sex+", email='"+emai+'\''+'}';
    }
}

测试类

publicclassDom4JTest2 {
@TestpublicvoidparseToList() throwsException {
// 1.导入Dom4J框架// 2.创建SAXReader对象SAXReadersaxReader=newSAXReader();
// 3.加载XML文件称为Document对象Documentdocument=saxReader.read(Dom4JTest2.class.getResourceAsStream("/Contacts.xml"));
// 4.获取根元素Elementroot=document.getRootElement();
// 5.提取contact子元素List<Element>contactEles=root.elements("contact");
// 6.准备ArrayList集合封装联系人信息List<Contact>contactList=newArrayList<>();
// 7.遍历contact子元素for (ElementcontactEle : contactEles) {
// xml文件中的值都是文本,需要使用包装类进行类型转换// 此处不能用强转,需要使用类型转换,强转必须保证被强转的变量类型就是强转后的类型才可以intcontactId=Integer.valueOf(contactEle.attributeValue("id"));
booleancontactIsVip=Boolean.valueOf(contactEle.attributeValue("vip"));
StringcontactName=contactEle.elementTextTrim("name");
charcontactSex=contactEle.elementTextTrim("gender").charAt(0);
StringcontactEmai=contactEle.elementTextTrim("email");
// 8.每一个子元素都是一个联系人对象// 9.把联系人对象加入到contactList集合中contactList.add(newContact(contactId, contactIsVip,
contactName, contactSex, contactEmail));
        }
// 10.遍历contactList集合for (Contactcontact : contactList) {
System.out.println(contact);
        }
    }
}

程序运行结果如下:

Contact{id=1, vip=true, name='潘金莲', sex=女, email='panpan@itcast.cn'}

Contact{id=2, vip=false, name='武松', sex=男, email='wusong@itcast.cn'}

Contact{id=3, vip=false, name='武大狼', sex=男, email='wuda@itcast.cn'}

注:xml文件中的值都是文本,需要进行类型转换不能用强转强转必须保证被强转的变量类型就是强转后的类型向下转型才可以类型转换是不同类型之间的变量的相互转换

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

一键修改所有出现该变量的变量名:Shift + F6。

3.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<Node> selectNodes("表达式")

获取符合表达式的元素集合

 

Xpath的四大检索方案:绝对路径、相对路径、全文检索、属性查找

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

XPath:相对路径:采用相对路径获取当前元素下一级contact 节点的name子节点并打印信息:./子元素/孙元素,从当前元素开始,一级一级向下查找,不能跨级。

XPath:全文搜索:直接全文搜索所有的name元素并打印。

//contact:找contact元素,无论元素在哪里。

//contact/name:找name,无论在哪一级,但name一定是contact的子节点。

//contact//name:contact无论在哪一种,name只要是contact的子孙元素都可以找到。

XPath:属性查找:在全文中搜索属性,或者带属性的元素。

//@属性名:查找属性对象,无论是哪个元素,只要有这个属性即可。

//元素[@属性名]:全文搜索查找含有此属性的元素对象。

//元素//[@属性名=‘值’]:全文搜索查找含有此属性且属性值值为的元素对象。

4.设计模式:工厂模式

什么是工厂设计模式?

之前我们创建类对象时,都是使用new对象的形式创建,在很多业务场景下也提供了不直接new的方式。

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

工厂设计模式的作用:

工厂的方法可以封装对象的创建细节,比如:为该对象进行加工和数据注入。

可以实现类与类之间的解耦操作,只需要在FactoryPattern中维护,其他使用到的地方一并修改(核心思想)。

示例代码如下:

电脑类

publicabstractclassComputer {
privateStringname;
privatedoubleprice;
publicComputer() {
    }
abstractvoidstart();
publicStringgetName() {
returnname;
    }
publicvoidsetName(Stringname) {
this.name=name;
    }
publicdoublegetPrice() {
returnprice;
    }
publicvoidsetPrice(doubleprice) {
this.price=price;
    }
}

苹果电脑类

publicclassMacextendsComputer{
@Overridevoidstart() {
System.out.println(this.getName() +"苹果电脑启动了");
    }
}

华为电脑类

publicclassHuaweiextendsComputer{
@Overridevoidstart() {
System.out.println(this.getName() +"华为电脑启动了");
    }
}

工厂类

publicclassFactoryPattern {
/*定义一个方法,创建对象并返回*/publicstaticComputercreatComputer(Stringinfo) {
switch (info) {
case"华为":
Computerc=newHuawei();
c.setName("Huawei pro 16");
c.setPrice(5999);
returnc;
case"苹果":
Computerc2=newMac();
c2.setName("Mac pro 2");
c2.setPrice(11999);
returnc2;
default:
returnnull;
        }
    }
}

工厂模式测试类

publicclassFactoryDemo {
publicstaticvoidmain(String[] args) {
Computerc1=FactoryPattern.creatComputer("华为");
c1.start(); // Huawei pro 16华为电脑启动了Computerc2=FactoryPattern.creatComputer("苹果");
c2.start(); // Mac pro 2苹果电脑启动了    }
}

5.设计模式:装饰模式

什么是装饰设计模式?

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

装饰设计模式的作用:

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

装饰模式示例如下图所示。

DeclarationPattern.png

装饰模式具体步骤如下:

定义父类。

② 定义原始类,继承父类,定义功能。

③ 定义装饰类,继承父类,包装原始类在原始类的基础上进行方法改进,增强功能

示例代码如下:

接口类(共同父类)

publicabstractclassInputStream {
publicabstractintread();
publicabstractintread(byte[] buffer);
}

原始类

publicclassFileInputStreamextendsInputStream {
@Overridepublicintread() {
System.out.println("以低性能的方式读取了一个字节a");
return97;
    }
@Overridepublicintread(byte[] buffer) {
buffer[0] =97;
buffer[1] =98;
buffer[2] =99;
System.out.println("以低性能的方式读取了一个字节数组"+Arrays.toString(buffer));
return3;
    }
}

装饰类

publicclassBufferedInputStreamextendsInputStream {
privateInputStreamis;
publicBufferedInputStream(InputStreamis) {
this.is=is;
    }
@Overridepublicintread() {
System.out.println("提供8kb的缓冲区,提高读取性能");
returnthis.is.read();
    }
@Overridepublicintread(byte[] buffer) {
System.out.println("提供8kb的缓冲区,提高读取性能");
returnthis.is.read(buffer);
    }
}

测试类

publicclassDecoratorPattern {
publicstaticvoidmain(String[] args) {
InputStreamis=newBufferedInputStream(newFileInputStream());
System.out.println(is.read());
System.out.println(is.read(newbyte[3]));
    }
}

程序运行结果如下:

提供8kb的缓冲区,提高读取性能

以低性能的方式读取了一个字节a

97

提供8kb的缓冲区,提高读取性能

以低性能的方式读取了一个字节数组[97, 98, 99]

3

相关文章
|
1月前
|
存储 缓存 Java
java基础:IO流 理论与代码示例(详解、idea设置统一utf-8编码问题)
这篇文章详细介绍了Java中的IO流,包括字符与字节的概念、编码格式、File类的使用、IO流的分类和原理,以及通过代码示例展示了各种流的应用,如节点流、处理流、缓存流、转换流、对象流和随机访问文件流。同时,还探讨了IDEA中设置项目编码格式的方法,以及如何处理序列化和反序列化问题。
67 1
java基础:IO流 理论与代码示例(详解、idea设置统一utf-8编码问题)
|
1月前
|
设计模式 PHP 开发者
PHP中的设计模式:桥接模式的解析与应用
在软件开发的浩瀚海洋中,设计模式如同灯塔一般,为开发者们指引方向。本文将深入探讨PHP中的一种重要设计模式——桥接模式。桥接模式巧妙地将抽象与实现分离,通过封装一个抽象的接口,使得实现和抽象可以独立变化。本文将阐述桥接模式的定义、结构、优缺点及其应用场景,并通过具体的PHP示例代码展示如何在实际项目中灵活运用这一设计模式。让我们一起走进桥接模式的世界,感受它的魅力所在。
|
1月前
|
设计模式 存储 数据库连接
PHP中的设计模式:单例模式的深入解析与实践
在PHP开发中,设计模式是提高代码可维护性、扩展性和复用性的关键技术之一。本文将通过探讨单例模式,一种最常用的设计模式,来揭示其在PHP中的应用及优势。单例模式确保一个类仅有一个实例,并提供一个全局访问点。通过实际案例,我们将展示如何在PHP项目中有效实现单例模式,以及如何利用这一模式优化资源配置和管理。无论是PHP初学者还是经验丰富的开发者,都能从本文中获得有价值的见解和技巧,进而提升自己的编程实践。
|
1月前
|
XML Web App开发 JavaScript
XML DOM 解析器
XML DOM 解析器
|
1月前
|
设计模式 算法 PHP
PHP中的设计模式:策略模式的深入解析与实践
【10月更文挑战第9天】 策略模式是一种行为设计模式,它允许在运行时选择算法的行为。在PHP开发中,通过使用策略模式,我们可以轻松切换算法或逻辑处理方式而无需修改现有代码结构。本文将深入探讨策略模式的定义、结构以及如何在PHP中实现该模式,并通过实际案例展示其应用价值和优势。
30 1
|
1月前
|
设计模式 算法 PHP
PHP中的设计模式:策略模式的深入解析与应用
【10月更文挑战第8天】 在软件开发的浩瀚宇宙中,设计模式如同星辰指引,照亮了代码设计与架构的航道。本文旨在深入探索PHP语境下策略模式(Strategy Pattern)的精髓,不仅剖析其内核原理,还将其融入实战演练,让理论在实践中生根发芽。策略模式,作为解决“如何优雅地封装算法族”的答案,以其独特的灵活性与扩展性,赋予PHP应用以动态变换行为的能力,而无需牵动既有的类结构。
27 2
|
1月前
|
XML Web App开发 JavaScript
XML DOM 解析器
XML DOM 解析器
|
1月前
|
设计模式 算法 PHP
PHP中的设计模式:策略模式的深入解析与实践
在PHP开发中,设计模式是提高代码可读性、可维护性和扩展性的重要工具。本文将深入探讨策略模式这一行为型设计模式,通过分析其定义、结构、使用场景以及在PHP中的实际应用,帮助开发者更好地理解和运用策略模式来优化自己的项目。不同于传统摘要的简洁概述,本文摘要部分将详细阐述策略模式的核心理念和在PHP中的实现方法,为读者提供清晰的指引。
|
1月前
|
XML Web App开发 JavaScript
XML DOM 解析器
XML DOM 解析器
|
1月前
|
设计模式 算法 PHP
PHP中的设计模式:策略模式的深入解析与实践
【10月更文挑战第12天】 在软件开发的世界中,设计模式是解决常见问题的最佳实践。它们不是具体的代码,而是一种编码和设计经验的总结。在PHP开发中,合理运用设计模式可以极大地提高代码的可维护性、扩展性和复用性。本文将深入探讨策略模式(Strategy Pattern)的原理、实现方式及其在PHP中的应用。通过具体示例,我们将展示如何利用策略模式来解耦算法与对象,从而让代码更加灵活和易于管理。
19 0

推荐镜像

更多
下一篇
无影云桌面