今日内容:
[重点]a.XML(作为框架的配置文件)
[重点]b.Dom4J(第三方框架,用来解析XML文件)
[理解]c.正则表达式
XML的介绍以及版本
XML(EXtensible Markup Language): 可扩展的标记语言
语言:XML也是一种语言
标记:标签 <开始标签> </结束标签>
可扩展: 标签可以随意扩展
XML的版本
XML 1.0 (99.9999%都使用该版本)
XML 1.1 (基本没人使用)
XML 与 HTML 的主要差异
a.XML是可扩展的标记 HTML是预先定义好的标记
b.XML主旨是传输和存储数据 HTML主旨是显示数据
XML小案例
需求:
使用XML,保存一个Person的信息(id,姓名,年龄)
编写
在Java代码:
public class Person{
String id;
String name;
int age;
String sex;
//其他省略
}
一个Person就是一个对象:
Person p1 = new Person("007","张三",20,"男");
Person p2 = new Person("008","李四",30,"女");
把多个对象添加到一个集合中:
ArrayList<Person> persons = new ArrayList<Person>();
persons.add(p1);
persons.add(p2);
在XML中:
<persons>
<person id="007">
<name>张三</name>
<age>20</age>
<sex>男</sex>
</person>
<person id="008">
<name>李四</name>
<age>30</age>
<sex>女</sex>
</person>
</persons>
运行
使用浏览器打开即可(火狐和谷歌)
XML的作用
a.传输数据(基本上被json代替)
b.保存数据(a.真的用于保存数据就像案例中 b.作为框架的配置文件)
XML的组成元素**********************
文档声明
什么是文档声明: 表明该文件是一个XML的文档
<?xml version="1.0" encoding="utf-8" ?>
a.文档声明必须出现在XML文档第0行第0列(左上角)
b.文档声明中有两个属性:version,encoding
其中version表示XML的版本,必须写,值是"1.0"
其中encoding表示XML的编码,可以不写(不建议),值是"utf-8"
元素element/标签(Tag)/节点(Node)
a.XML最主要的组成部分:
元素<Element>/标签<Tag>/节点(Node)
格式: <开始标签>标签体</结束标签>
b.普通的标准由: <开始标签> + 标签体 + </结束标签> 三部分组成
c.标签体: 可以是其他普通标签也可以普通文本内容
d.空标签: <开始标签></结束标签> 建议写成自闭合标签:<标签/>
e.标签的名字:
a.大小写区分
b.不要使用特殊符号(空格,冒号,分号等)
c.不建议以xml相关的开头
f.一个标准的XML文档,有且仅有一个根标签
属性attribute
a.属性必须写在开始标签内
b.属性的格式: 属性名="属性值",无论属性值是什么类型的,必须使用""或者''引起来
c.一个标签中属性可以是0-N个,但是不允许有相同名字的属性
d.属性名不可以有空格等特殊符号,必须以字母开头
注释
<!--注释内容-->
<!--
注释内容
注释内容
注释内容
-->
转义字符
< --> <
> --> >
" --> "
' --> '
& --> &
<?xml version="1.0" encoding="UTF-8"?>
<code>
for(int i = 0;i < 10;i++){
System.out.println("<code>");
}
</code>
字符区/CDATA区(了解)
在字符区中所有的字符,我们正常写即可,XML会帮助我们自动转义
字符区:
<![CDATA[
字符区内容
]]>
<?xml version="1.0" encoding="UTF-8"?>
<code>
<![CDATA[
for(int i = 0;i < 10;i++){
System.out.println(""
);
}
]]>
</code>
什么是DTD约束
DTD约束: 文档类型定义约束
作用: 用于约束我们写的XML文档
DTD约束体验
我们的重点不是学习DTD怎么写,而是只要根据DTD编写出符合要求XML即可!!!!!!
a.复制bookshelf.dtd文件
b.创建我们的XML文档
c.在我们的XML文档,引入DTD约束
d.根据IDEA的提示,完成XML即可
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE 书架 SYSTEM "bookshelf.dtd">
<书架>
<书>
<书名>三国演义</书名>
<作者>罗贯中</作者>
<售价>100</售价>
</书>
<书>
<书名>水浒传</书名>
<作者>施耐庵</作者>
<售价>200</售价>
</书>
</书架>
DTD约束语法(了解)
DTD的引入
内部DTD:
直接将DTD写到某个XML内部 -- 只能给当前的XML使用(一般不用)
外部DTD -- 本地DTD -- 一般用于公司内部
<!DOCTYPE 根元素 SYSTEM "bookshelf.dtd">
外部DTD -- 公共DTD -- 所有公司均可使用,一般是各种框架提供
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
DTD中的数量词
标签名* ---> 表示该标签可以出现0-N次
标签名+ ---> 表示该标签可以出现1-N次
标签名? ---> 表示该标签可以出现0-1次
标签1,标签2,标签3 ---> 表示三个标签必须按照前后顺序出现
标签1|标签2|标签3 ---> 表示三个标签可以选中出现其中一个
其他语法了解即可
有关属性和类型和可选说明我们了解即可
什么是Schema约束
也是一种XML约束,比DTD更加强大(主要强大在数据类型的约束上)
Schema约束文档,本质上也是一个XML文档,但是后缀是.xsd
Schema约束体验
a.复制schema约束文件bookshelf.xsd
b.创建我们自己的XML文档
c.在我们的XML文档中引入xsd约束
d.根据IDEA的提示,编写符合要求的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 bookshelf.xsd">
<书>
<书名>三国演义</书名>
<作者>罗贯中</作者>
<售价>100</售价>
</书>
<书>
<书名>红楼梦</书名>
<作者>曹雪芹</作者>
<售价>200</售价>
</书>
</书架>
Schema的语法和命名空间(了解即可)
Schema约束中的标签,属性,数据类型等我们了解即可
在Schemal约束中有一种称为命名空间的东西:
命名空间 类似于Java中的包
package 包名;
targetNamespace="http://www.itcast.cn"
使用命名空间时:
xmlns="http://www.itcast.cn" (默认名空间)
xmlns:别名="http://www.itcast.cn" (别名命名空间)
我们学习XML约束,不是学习如何编写DTD和Schema,
而是根据DTD和Schema约束,配合IDEA提示完成符合要求的XML!!!!
通过Java代码,解析出XML中所保存的数据
XML的解析方式(理论,思想):
DOM解析: 把整个XML读取到内存中,然后整体解析,解析后返回一个Document对象
a)优点:元素与元素之间保留结构关系,故可以进行增删改查操作。
b)缺点:XML文档过大,可能出现内存溢出
SAX解析: 将XML文件读一行,解析一行,释放这一行
a)优点:处理速度快,可以处理大文件
b)缺点:只能读,逐行后将释放资源,解析操作繁琐。
PULL解析: 是Android的解析方式
XML的解析器(代码实现):
对DOM解析理论和SAX解析理解进行具体的代码实现
解析器不一定是Java代码,而且API非常繁琐(因为需要考虑每一个细节)
XML的解析开发包(对代码进一步封装):
对于解析器中繁琐的API进行封装,封装之后API大大简化了我们的开发
常见的解析开发包:
Dom4j解析开发包(使用Dom解析方式)
DOM解析的原理
将整个XML一次性读取到内存进行解析,解析后返回一个Document对象(XML文档对象)
DOM树的结构模型
<?xml version="1.0" encoding="UTF-8"?>
<books> <book id="0001">
<name>JavaWeb开发教程</name>
<author>张孝祥</author>
<sale>100.00元</sale>
</book>
<book id="0002">
<name>三国演义</name>
<author>罗贯中</author>
<sale>100.00元</sale>
</book>
</books>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-F8HbzIV9-1578312782570)(img/image-20200106113529119.png)]
DOM4J的jar包和常用API
DOM4JAPI:
核心类:SaxReader(用于加载XML文件)
构造:
public SaxReader() 构造器
public Document read(String url); 将文件读取到内存并解析,解析后返回Document对象
Document类:
public Element getRootElement() 获得根元素
Element类:
public List elements([String name]); 列出当前元素[指定名字]下所有的子元素
public Element element([String name]); 获取当前元素下[指定名字]的第一子元素
public String getName(); 获取当前元素的元素名(标签名)
public String attributeValue(String attrName);获取当前元素的某个指定属性值
public String getText(); 获取当前元素的文本内容
public String elementText(Sting ele);获取当前元素下指定第一个子元素的文本
DOM4J代码演示
books.xml
<books>
<book id="0001">
<name>JavaWeb开发教程</name>
<author>张孝祥</author>
<sale>100.00元</sale>
</book>
<book id="0002">
<name>三国演义</name>
<author>罗贯中</author>
<sale>100.00元</sale>
</book>
</books>
注意:解析的时候目前不需要引入约束
/**
* 解析books.xml
*/
public class Dom4JDemo {
public static void main(String[] args) throws DocumentException {
//1.Dom4J核心类,SAXReader
SAXReader reader = new SAXReader();
//2.读取整个XML,解析返回Document对象
//从Dom4JDemo的文件的根文件找
// InputStream in = Dom4JDemo.class.getResourceAsStream("/books.xml");
//从src下找
InputStream in = Dom4JDemo.class.getClassLoader().getResourceAsStream("books.xml");
Document document = reader.read(in);
// 3.获取根元素
Element rootElement = document.getRootElement();
System.out.println(rootElement.getName());
// 4.获取所有的子元素
List<Element> elements = rootElement.elements();
// 5.遍历集合
for (Element bookElement : elements) {
//6.获取book元素的属性
String idValue = bookElement.attributeValue("id");
System.out.println(bookElement.getName());
System.out.println("id属性的值是:"+idValue);
//7.获取book元素的子元素
List<Element> eles = bookElement.elements();
//8.遍历
for (Element ele : eles) {
//9.获取元素名字
System.out.println(ele.getName());
//10.获取元素的文本
String text = ele.getText();
System.out.println("文本内容是:"+text);
}
}
}
}
什么是XPath
通过"XPath路径表达式"来快速获取整个XML文档中我们需要的元素或者属性
XPath使用步骤
public List selectNodes("路径表达式"); 快速获取多个符合要求的节点
public Element selectSingleNode("表达式"); 快速获取符合要求的单个节点
XPath语法(了解)
绝对路径表达式方式 例如: /元素/子元素/子子元素...
相对路径表达式方式 例如: 子元素/子子元素.. 或者 ./子元素/子子元素..
全文搜索路径表达式方式 例如: //子元素//子子元素
条件筛选/谓语表达式方式 例如://元素[@attr1=value]
public class XPathDemo {
public static void main(String[] args) throws DocumentException {
//1.Dom4J核心类,SAXReader
SAXReader reader = new SAXReader();
//2.读取整个XML,解析返回Document对象
// InputStream in = Dom4JDemo.class.getResourceAsStream("/books.xml");
InputStream in = Dom4JDemo.class.getClassLoader().getResourceAsStream("books.xml");
Document document = reader.read(in);
//3.使用Xpath
//a.绝对路径
List<Node> nodes = document.selectNodes("/books/book/sale");
for (Node node : nodes) {
String text = node.getText();
System.out.println(text);
}
//c.全文搜索路径
List<Node> nodes1 = document.selectNodes("//name");
for (Node node : nodes1) {
System.out.println(node.getText());
}
//d.条件筛选
Node node = document.selectSingleNode("//book[@id=0001]");
System.out.println(node.getName());
//b.相对路径
Node node1 = node.selectSingleNode("name");
System.out.println(node1.getText());
}
}
什么是正则表达式:
本质上就一个字符串,和普通字符串的区别在于其内容
普通的字符串的内容就是内容,正则表达式的内容而是代表某个规则
比如:
String str = "HelloWorld"; 普通字符串
String regex = "\\d{4,9}"; 正则表达式
作用: 可以通过正则表达式来判断某个字符串是否符合该规则
在String类中有一个方法:
public boolean matches(String regex); 判断当前字符串是否正则的规则,符合则true
案例:
需求:下面的程序让用户输入一个QQ号码,我们要验证:
QQ号码必须是5--15位长度
而且必须全部是数字
而且首位不能为0
public class RegexDemo {
public static void main(String[] args) {
// 案例:
// 需求:下面的程序让用户输入一个QQ号码,我们要验证:
// QQ号码必须是5--15位长度
// 而且必须全部是数字
// 而且首位不能为0
System.out.println("请输入您的QQ号码:");
String qq = new Scanner(System.in).nextLine();
//判断
if (qq.length() < 5 || qq.length() > 15) {
System.out.println("长度不满足...");
return;
}
for (int i = 0; i < qq.length(); i++) {
char ch = qq.charAt(i);
if (ch < '0' || ch > '9') {
System.out.println("不全是数字..");
return;
}
}
if (qq.charAt(0) == '0') {
System.out.println("首位不能为0");
return;
}
System.out.println("您的QQ是合法的!!");
//正则表达式,他是一位一位判断的 1345563
boolean b = qq.matches("[1-9][0-9]{4,14}");
if (b) {
System.out.println("您的QQ是合法的!!");
}else{
System.out.println("您的QQ不合法的!!");
}
}
}
public class RegexDemo01 {
public static void main(String[] args) {
String str = "ead";
//1.验证str是否以h开头,以d结尾,中间是a,e,i,o,u中某个字符
System.out.println(str.matches("h[aeiou]d"));
//2.验证str是否以h开头,以d结尾,中间不是a,e,i,o,u中的某个字符
System.out.println(str.matches("h[^aeiou]d"));
//3.验证str是否a-z的任何一个小写字符开头,后跟ad
System.out.println(str.matches("[a-z]ad"));
//4.验证str是否以a-d或者m-p之间某个字符开头,后跟ad
System.out.println(str.matches("[a-dm-p]ad"));
}
}
public class RegexDemo02 {
public static void main(String[] args) {
String str = "bad";
//1.要求字符串是小写(a,e,i,o,u元音字符)字符开头,后跟ad
System.out.println(str.matches("[^aeiou&&a-z]ad"));
//2.要求字符串是aeiou中的某个字符开头,后跟ad
System.out.println(str.matches("[a|e|i|o|u]ad"));
}
}
public class RegexDemo03 {
public static void main(String[] args) {
String str = "2a8";
//1.验证str是否3位数字
System.out.println(str.matches("\\d\\d\\d"));
//2.验证手机号:1开头,第二位:3/5/8,剩下9位都是0-9的数字
str = "13513153355";
System.out.println(str.matches("1[358]\\d{9}"));
//3.验证字符串是否以h开头,以d结尾,中间是任何字符
str = "h d";
System.out.println(str.matches("h.d"));
//4.验证str是否是:had.
str = "had.";
System.out.println(str.matches("had\\."));
}
}
public class RegexDemo04 {
public static void main(String[] args) {
String str = "";
//1.验证str是否是三位数字
str = "012";
System.out.println(str.matches("\\d{3}"));
//2.验证str是否是多位数
str = "82345678987432345689943234578";
System.out.println(str.matches("\\d{2,}"));
//3.验证str是否是手机号:
str = "13813183388";
System.out.println(str.matches("1\\d{10}"));
//4.验证小数:必须出现小数点,但是只能出现1次
str = "3.0";
System.out.println(str.matches("[0-9]+\\.[0-9]+"));
//5.验证小数:小数点可以不出现,也可以出现1次
str = "3.0";
System.out.println(str.matches("[0-9]+\\.?[0-9]+"));
//6.验证小数:要求匹配:3、3.、3.14、+3.14、-3.
str = "3.14";
System.out.println(str.matches("[+-]?3\\.?1?4?"));
//7.验证qq号码:1).5--15位;2).全部是数字;3).第一位不是0
str = "38385438";
System.out.println(str.matches("[1-9]\\d{4,14}"));
}
}
public class RegexDemo05 {
public static void main(String[] args) {
String str = "DG8FV-B9TKY-FRT9J-99899-XPQ4G";
//验证这个序列号:分为5组,每组之间使用-隔开,每组由5位A-Z或者0-9的字符组成
System.out.println(str.matches("([A-Z0-9]{5}-){4}[A-Z0-9]{5}"));
}
}
public String[] split(String regex); 以指定的分割符来分割字符串,分割符支持正则表达式
public class RegexDemo06 {
public static void main(String[] args) {
String str = "18 4 567 99 56";
//1.使用空格
String[] strs = str.split(" ");
for (String s : strs) {
System.out.println(s);
}
//2.使用正则
String[] strs1 = str.split(" +");
for (String s : strs1) {
System.out.println(s);
}
System.out.println("-----------");
String s2 = "3566.+.3577.+.45667..++..34667";
String[] ss = s2.split("\\.+\\++\\.+");
for (String s : ss) {
System.out.println(s);
}
}
}
public String replaceAll(String regex, String replacement);将当前字符串中的所有的子串替换为其他字符串
public class RegexDemo07 {
public static void main(String[] args) {
String content = "TMD我去TMD你大爷,TMD,滚!!TMD";
//敏感词过滤(替换)
String s1 = content.replaceAll("TMD", "***");
System.out.println(s1);
//将下面字符串中的"数字"替换为"*"
String str = "jfdk432jfdk2jk24354j47jk5l31324";
String s2 = str.replaceAll("\\d", "*");
System.out.println(s2);
}
}