admin管理员组

文章数量:1579383

第一章 正则表达式

1 理解

1.1 正则表达式

  • 正则表达式是用来描述具有一定特征的字符串的特殊字符串。Regular Expression。

    a+b*c : a+ c 个的 b
    (d+e)*f:()->组,改变了优先级 ,f 个的 d+e
    a+b*c+(d+e)*f : 组合成复杂的表达式
    

1.2 目标

  • 简单可以手写,复杂的拷贝,略作修改。Java中使用正则会用即可.

1.3 入门示例

ab*: a 若干个 b ->* 零个及以上 ,匹配: a ab abbbbb abbbbbbb 不能 bbbbb。
(cd)*: ()->组,改变了优先级 ,若干个 cd,匹配: “” cd cdcd cdcdcd
ab*(cd)*:a 若干个 b 和若干个 cd 匹配: a ab abbbbb abbbbbbb acd acdcd abbbbbcd abcd
ab*|(cd)*: |或的优先级低 匹配: a ab cd
ab|c : 匹配 ab c

1.4 作用

  • 验证、查找、替换、分割 。

2 字符集

  • 默认情况下区分大小写。

2.1. 普通字符

  • 写什么,匹配什么
  • 非特殊含义以外的字符,如 a b 中国 。 普通字符精确匹配

2.2. 元字符与转义

  • 14个元字符:[],(),{},\,^,$,.,*,+,?,|有特殊含义
  • 转义字符:\+字母

3 字符类

3.1.自定义

由 [] 组,只匹配一个, 需要注意以下几个:

  • ^ : 如果在第一个位置,表示取反的含义。

  • :表示一个区间即范围

  • ] : 最近一个位置为:结束 ,如果要表示普通的]请加 \

  • \ : 转义

  • . 在字符类中不是代表任意的字符,代表自身 . 的含义。 如果需要表示原有的含义,挪动位置或者加
    \ 。

[ae134] -> a e 1 3 4
[(as)] ->a s ( )
[a-z] ->小写字母
[-\]a-z\[] -> -[] 及小写字母

3.2. 默认|标准字符类

字符含义
\ddigit[0-9] , [0123456789]
\wword [A-Za-z0-9]
\sspace 空格,制表符,换行符
.多行模式(缺省):除了换行符\r\n以外的任意一个字符, [^\n\r] ;单行模式:可以匹配包含换行符在内的任意一个字符
\D[\d][0123456789][^0-9]
\W[^\w] 非字母, 数字, _, 即空白,标点符号及中文
\S[^\s]
h[ea]llo –>hello hallo
h(e|a)llo ->hello hallo
[\-\\abc] -> - \ a b c
\d\s ->一个数字和一个空白
[\d\s] –> 数字 或 空白

3.3. 量词

  • 匹配的过程中,需要指定次数

  • * :0个及以上

  • + :一个及以上

  • ?:0个或一个

  • {n}:n次,非负数

  • {n,}:大于等于n次

  • {n,m}:大于等于n次,小于等于m次

co*ke –> 不限个数的 O
co+ke –>至少一个 O
co?ke ->1 个或零个 O
co{0}ke ->0 个
co{5,}ke –>5 次及以上
co{5,8}ke –> 至少 5 次,最多 8 次
[1-9]\d{3} –>大于等于 1000 小于等于 9999 的数
[1-9]\d{2,4} –>大于等于 100 小于等于 99999 的数
1[34578]\d{9} : 匹配手机号
<[a-zA-Z]+\d?> ->网页标签
<[A-Za-z][A-Za-z0-9]*> ->网页标签

3.4. 贪婪模式

3.4.1 理解
  • 在匹配次数不定时如 *, {n,}, + 匹配字符越多越好,默认模式即”贪婪模式”

  • 贪婪模式 greedy(匹配字符越多越好,可回溯)

  • ? 懒惰模式 lazy reluctant (匹配字符越少越好,可回溯)

  • +独占模式 possessive(匹配字符越多越好,不可回溯) 用的较少 cokecolacoooooooooooooke

    .*o –>贪婪模式
    .{2,}o–>贪婪模式
    .{2,}?o –>懒惰模式
    .{2,}+o –>独占模式,不可回溯 没有匹配到内容。
    <.+?> ->找出标签 不要标签内的内容。不是<.+>
    <[^>]+>->找出标签 不要标签内的内容。不是<.+>
    

3.4.2 阻止贪婪有两种方式

  • 量词后面使用 ?
  • 使用取反

4 边界

  • 边界不占用宽度,只是一个界限

  • ^ :开始 \b :单词边界 \B :非单词边界 $ :结束

    • ^ :多行代表每行头 单行代表整个字符串的开始

    • $ : 多行代表每行尾 单行代表字符串的结尾

    • \b : 匹配前面或后面的不是\w

    • \B : 匹配前面或后面的是\w

      查找开头的 hello -> ^hello
      找出 独立的单词 world -> \bworld\b
      查找结尾的 world -> world$
      

5 选择符与分组

5.1 选择符|

  • | ->优先级低 ,满足匹配则停止,不会查找更优的方案
  • he|hello –>只匹配 he,不匹配 hello
  • hello|he->匹配 he 与 hello

5.2 分组 ()

匹配 ab c -> ab|c
匹配 ab ac -> a(b|c)
只匹配 get -> \bget\b
匹配 get 和 getValue -> getvalue|get get(value)?
获取 and or -> \band\b|\bor\b \b(and|or)\b
  • 反向引用: \ 内部默认缓存,从第一个左括号计算,编号为 1 开始。
    必须认识组编号,为 ( 的位置

    (")test\1 –> “第 1 个左括号中
    ((")test)\2 –> “第 2 个左括号中
    ((("))test)\3 –> “第 3 个左括号中
    ["'](.*?)["'] -> 错误的 找出合法的字符串"" 或''
    (["'])([^"']+)\1 ->找出合法的字符串"" 或''
    
  • 非捕获组: (?:xxx) : 不缓存组

    (["'])(?:[^"']+)\1 ->不缓存第二组,不能引用第二组
    (?:["'])(?:[^"']+)\1 –>所有的组都没有缓存,不能再引用了。
    
  • 找出合法的标签

    <(b)>(?:[^<]+)</\1> -> <b>13321</b>
    <([a-zA-Z]([a-zA-z]{1,5}|\d{1,2})?)>(?:[^<]+)</\1> -->找出合法的标签
    

5.3 模式修改符

  • (?ism )*****(?-ism)
  • i : insensitive 使正则表达式对大小写不敏感;(重点)
  • s : singleline 开启“单行模式”,即点号“.”匹配新行符;
  • m : multiline 开启“多行模式”,即“^”和“$”匹配新行符的前面和后面的位置
  • (?i)select(?-i) -> 不区分大小写。

6 零宽断言

前瞻(Lookahead) 后顾(Lookbehind)

(?=exp)先行断言,自身后面能匹配表达式exp
(?<=exp)后发断言,自身前面能匹配表达式exp
(?!exp)此位置后面不能匹配表达式exp
(?<!exp)此位置前面不能匹配表达式exp

7 java中使用正则

7.1 使用方法

  • String类中一些支持正则表达式语法的方法
    String[] split(String regex) 将此字符串拆分为给定 regular expression的匹配 项 。
    String replaceAll(String regex, String replacement) 将给定替换的给定 regular expression匹配的此字符串的每个子字符串替换。
    String replaceFirst(String regex, String replacement) 将给定替换的给定 regular expression匹配的此字符串的第一个子字符串替换。
    boolean matches(String regex) 判断此字符串是否与给定的 regular expression匹配。
  • 模式器 Pattern
    匹配器 Matcher

7.2 代码

public class Class002_Regex {
    public static void main(String[] args) {
        String reg = ".{3}(a{1,2}\\d{2})(hello|hi)";
        String str = "asdaa12hellodsaa34hi";

        //1. String类中一些支持正则表达式语法的方法
        System.out.println(Arrays.toString(str.split("\\.")));
        System.out.println(str.replaceAll("\\.","*"));

        //boolean matches(String regex) 判断此字符串是否与给定的 regular expression匹配。--->完整匹配
        if(str.matches("\\d{3}")){
            System.out.println("匹配");
        }

        //2.模式器 Pattern
        Pattern pattern = Pattern.compile(reg);
        Matcher matcher = pattern.matcher(str);
        //matches() 要求正则与指定字符串完整匹配返回true,否则返回false
        /*System.out.println(matcher.matches());*/

        //find() 判断是否存在满足条件的子串
        while(matcher.find()){
            //group() 获取当前查找到的子串
            System.out.println("查找到的子串: "+matcher.group()+"--->"+matcher.group(0));
            //group(index) 获取当前子串中第几组缓存的内容
            System.out.println("分组缓存内容: "+matcher.group(1)+"--->"+matcher.group(2));
        }
    }
}

8 常用正则大全

8.1 校验数字的表达式

1 数字:^[0-9]*$
2 n位的数字:^\d{n}$
3 至少n位的数字:^\d{n,}$
4 m-n位的数字:^\d{m,n}$
5 零和非零开头的数字:^(0|[1-9][0-9]*)$
6 非零开头的最多带两位小数的数字:^([1-9][0-9]*)+(.[0-9]{1,2})?$
7 带1-2位小数的正数或负数:^(\-)?\d+(\.\d{1,2})?$
8 正数、负数、和小数:^(\-|\+)?\d+(\.\d+)?$
9 有两位小数的正实数:^[0-9]+(.[0-9]{2})?$
10 有1~3位小数的正实数:^[0-9]+(.[0-9]{1,3})?$
11 非零的正整数:^[1-9]\d*$ 或 ^([1-9][0-9]*){1,3}$ 或 ^\+?[1-9][0-9]*$
12 非零的负整数:^\-[1-9][]0-9"*$ 或 ^-[1-9]\d*$
13 非负整数:^\d+$ 或 ^[1-9]\d*|0$
14 非正整数:^-[1-9]\d*|0$ 或 ^((-\d+)|(0+))$
15 非负浮点数:^\d+(\.\d+)?$ 或 ^[1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0$
16 非正浮点数:^((-\d+(\.\d+)?)|(0+(\.0+)?))$ 或 ^(-([1-9]\d*\.\d*|0\.\d*[1-
9]\d*))|0?\.0+|0$
17 正浮点数:^[1-9]\d*\.\d*|0\.\d*[1-9]\d*$ 或 ^(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-
9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*))$
18 负浮点数:^-([1-9]\d*\.\d*|0\.\d*[1-9]\d*)$ 或 ^(-(([0-9]+\.[0-9]*[1-9][0-9]*)|
([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*)))$
19 浮点数:^(-?\d+)(\.\d+)?$ 或 ^-?([1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0)$

8.2 校验字符的表达式

1 汉字:^[\u4e00-\u9fa5]{0,}$
2 英文和数字:^[A-Za-z0-9]+$ 或 ^[A-Za-z0-9]{4,40}$
3 长度为3-20的所有字符:^.{3,20}$
4 由26个英文字母组成的字符串:^[A-Za-z]+$
5 由26个大写英文字母组成的字符串:^[A-Z]+$
6 由26个小写英文字母组成的字符串:^[a-z]+$
7 由数字和26个英文字母组成的字符串:^[A-Za-z0-9]+$
8 由数字、26个英文字母或者下划线组成的字符串:^\w+$ 或 ^\w{3,20}$
9 中文、英文、数字包括下划线:^[\u4E00-\u9FA5A-Za-z0-9_]+$
10 中文、英文、数字但不包括下划线等符号:^[\u4E00-\u9FA5A-Za-z0-9]+$ 或 ^[\u4E00-
\u9FA5A-Za-z0-9]{2,20}$
11 可以输入含有^%&',;=?$\"等字符:[^%&',;=?$\x22]+
12 禁止输入含有~的字符:[^~\x22]+

8.3 3 特殊需求表达式

1 Email地址:^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$
2 域名:[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(/.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+/.?
3 InternetURL:[a-zA-z]+://[^\s]* 或 ^https://([\w-]+\.)+[\w-]+(/[\w-./?%&=]*)?$
4 手机号码:^(13[0-9]|14[5|7]|15[0|1|2|3|5|6|7|8|9]|18[0|1|2|3|5|6|7|8|9])\d{8}$
5 电话号码("XXX-XXXXXXX"、"XXXX-XXXXXXXX"、"XXX-XXXXXXX"、"XXXXXXXXXXX"、"XXXXXXX"和"XXXXXXXX):^(\(\d{3,4}-)|\d{3.4}-)?\d{7,8}$
6 国内电话号码(0511-4405222、021-87888822):\d{3}-\d{8}|\d{4}-\d{7}
7 身份证号:
15或18位身份证:^\d{15}|\d{18}$
15位身份证:^[1-9]\d{7}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}$
18位身份证:^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-
1])\d{4}$
8 短身份证号码(数字、字母x结尾):^([0-9]){7,18}(x|X)?$ 或 ^\d{8,18}|[0-9x]{8,18}|[0-
9X]{8,18}?$
9 帐号是否合法(字母开头,允许5-16字节,允许字母数字下划线):^[a-zA-Z][a-zA-Z0-9_]{4,15}$
10 密码(以字母开头,长度在6~18之间,只能包含字母、数字和下划线):^[a-zA-Z]\w{5,17}$
11 强密码(必须包含大小写字母和数字的组合,不能使用特殊字符,长度在8-10之间):^(?=.*\d)(?=.*
[a-z])(?=.*[A-Z]).{8,10}$
12 日期格式:^\d{4}-\d{1,2}-\d{1,2}
13 一年的12个月(01~09和1~12):^(0?[1-9]|1[0-2])$
14 一个月的31天(01~09和1~31):^((0?[1-9])|((1|2)[0-9])|30|31)$
15 钱的输入格式:
16 1.有四种钱的表示形式我们可以接受:"10000.00" 和 "10,000.00", 和没有 "分" 的 "10000" 和
"10,000":^[1-9][0-9]*$
17 2.这表示任意一个不以0开头的数字,但是,这也意味着一个字符"0"不通过,所以我们采用下面的形式:
^(0|[1-9][0-9]*)$
18 3.一个0或者一个不以0开头的数字.我们还可以允许开头有一个负号:^(0|-?[1-9][0-9]*)$
19 4.这表示一个0或者一个可能为负的开头不为0的数字.让用户以0开头好了.把负号的也去掉,因为钱总不能
是负的吧.下面我们要加的是说明可能的小数部分:^[0-9]+(.[0-9]+)?$
20 5.必须说明的是,小数点后面至少应该有1位数,所以"10."是不通过的,但是 "10" 和 "10.2" 是通过
的:^[0-9]+(.[0-9]{2})?$
21 6.这样我们规定小数点后面必须有两位,如果你认为太苛刻了,可以这样:^[0-9]+(.[0-9]{1,2})?$
22 7.这样就允许用户只写一位小数.下面我们该考虑数字中的逗号了,我们可以这样:^[0-9]{1,3}(,[0-
9]{3})*(.[0-9]{1,2})?$
23 8.1到3个数字,后面跟着任意个 逗号+3个数字,逗号成为可选,而不是必须:^([0-9]+|[0-9]{1,3}(,
[0-9]{3})*)(.[0-9]{1,2})?$
24 备注:这就是最终结果了,别忘了"+"可以用"*"替代如果你觉得空字符串也可以接受的话(奇怪,为什么?)
最后,别忘了在用函数时去掉去掉那个反斜杠,一般的错误都在这里
25 xml文件:^([a-zA-Z]+-?)+[a-zA-Z0-9]+\\.[x|X][m|M][l|L]$
26 中文字符的正则表达式:[\u4e00-\u9fa5]
27 双字节字符:[^\x00-\xff] (包括汉字在内,可以用来计算字符串的长度(一个双字节字符长度计2,
ASCII字符计1))
28 空白行的正则表达式:\n\s*\r (可以用来删除空白行)
29 HTML标记的正则表达式:<(\S*?)[^>]*>.*?|<.*? /> (网上流传的版本太糟糕,上面这个也仅仅能
部分,对于复杂的嵌套标记依旧无能为力)
30 首尾空白字符的正则表达式:^\s*|\s*$或(^\s*)|(\s*$) (可以用来删除行首行尾的空白字符(包括
空格、制表符、换页符等等),非常有用的表达式)
31 腾讯QQ号:[1-9][0-9]{4,} (腾讯QQ号从10000开始)
32 中国邮政编码:[1-9]\d{5}(?!\d) (中国邮政编码为6位数字)
33 IP地址:\d+\.\d+\.\d+\.\d+ (提取IP地址时有用)

第二章 XML

1 xml

1.1概念

  • 可扩展标记语言,xml是互联网数据传输的重要工具,它可以跨越互联网任何的平台,不受编程语言和
    操作系统的限制,可以说它是一个拥有互联网最高级别通行证的数据携带者。xml是当前处理结构化文
    档信息中相当给力的技术,xml有助于在服务器之间穿梭结构化数据,这使得开发人员更加得心应手的
    控制数据的存储和传输。
  • Xml用于标记电子文件使其具有结构性的标记语言,可以用来标记数据、定义数据类型,是一种允许用
    户对自己的标记语言进行定义的源语言。Xml是标准通用标记语言(SGML)的子集,非常适合Web传
    输。XML提供统一的方法来描述和交换独立于应用程序或供应商的结构化数据。

1.2 理解

  • xml是一个标记语言 <英文单词>
  • xml文件中标签可以根据需求自定义
  • xml文件的首行必须存在版本声明
  • xml文件中有且仅有一个跟标签|根元素 Persons,所有的子内容都定义在根元素中

1.2 重点

  • 学习xml文件的编写语法 *
  • 学习xml解析 *
  • 了解约束

1.3 特点与作用

1.3.1 特点
  • xml与操作系统、编程语言的开发平台都无关;
  • 实现不同系统之间的数据交互。
1.3.2 作用
  • 传输,存储,配置,解析…

  • 配置应用程序(servlet 配置,框架环境配置等)和网站

  • 数据交互

  • Ajax基石

1.4 属性
  • 开始标签上定义属性
  • 属性可以帮助更完整|完善的展示标签的作用

1.5 标签的分类

  • 单标签|自闭和标签
  • 双标签|闭合标签

2 XML解析

2.1 DOM4J解析

  • 查询,遍历
    1)创建流,加载xml文件
    2)获取Document对象
    3)遍历
  • 写出
  • 创建
  • 删除或者修改

2.2 遍历

2.2.1 XML文件
<?xml version="1.0" encoding="UTF-8" ?>
<persons>
    <!--标记语言的注释-->
    <!--
        1.xml是一个标记语言  <英文单词>
        2.xml文件中标签可以根据需求自定义
        3.xml文件的首行必须存在版本声明
        4.xml文件中有且仅有一个跟标签|根元素 Persons,所有的子内容都定义在根元素中
        5.xml的作用: 传输,存储,配置,解析...
        6.属性: 开始标签上定义属性
            属性可以帮助更完整|完善的展示标签的作用

        7.标签的分类:
            单标签|自闭和标签
            双标签|闭合标签
    -->
    <person id="1001">
        <name>张三</name>
        <age>18</age>
        <location loc="上海"/>
    </person>
    <person>
        <name>lii</name>
        <age>18</age>
    </person>
    <student>
        <name>wangwu</name>
        <age>18</age>
    </student>
</persons>
2.2.2 解析
public class Class001_XML {
    public static void main(String[] args) throws DocumentException {
        //创建流,加载XML文件
        SAXReader reader = new SAXReader();
        //获取document对象
        Document document = reader.read(new File("src/Persons.XML"));
        // 3)遍历
        //获取根节点
        Element root = document.getRootElement();
        System.out.println("根元素标签名:"+root.getName());
        //获取子元素
        List<Element> list = root.elements();
        //遍历子元素
        list.forEach(e->{
            System.out.println("标签名"+e.getName()+"id属性"+e.attributeValue("id"));
            //迭代所有子元素的迭代器
            Iterator<Element> it = e.elementIterator();
            while (it.hasNext()){
                Element ele = it.next();
                System.out.println(ele.getName()+ele.getData());
            }
        });
    }
}

2.3 写出与创建

public class Class002_XML {
    public static void main(String[] args) throws DocumentException, IOException {
        writeToFile(creatDocument(),"src\\whl.xml");

    }
  
    //写出
    public static void writeToFile(Document document,String path) throws IOException {
        //1.  构建XMLWriter
        XMLWriter writer = null;
        //2.构建输出格式
        OutputFormat format = OutputFormat.createPrettyPrint();
        writer = new XMLWriter(new FileWriter(path),format);
        //3.写出
        writer.write(document);
        //4.刷出
        writer.flush();
        //5.关闭
        writer.close();
    }

    /*
        创建Document

        <yjxxt>
            <shyjxxt>
                <location>上海市浦东新区</location>
                <date>2021-10-10</date>
            </shyjxxt>
            <bjyjxxt>
                <location>北京市朝阳区</location>
                <date>2022-12-12</date>
            </bjyjxxt>
        </yjxxt>
     */
    public static Document createDocument(){
        //1.创建Document
        Document document = DocumentHelper.createDocument();
        //2.添加根元素
        Element root = document.addElement("yjxxt");
        //3.根元素中添加子元素
        Element shyjxxt = root.addElement("shyjxxt");
        Element bjyjxxt = root.addElement("bjyjxxt");

        shyjxxt.addElement("location").addText("上海市浦东新区");
        shyjxxt.addElement("date").addText("2021-10-10");
        bjyjxxt.addElement("location").addText("北京市朝阳区");
        bjyjxxt.addElement("date").addText("2022-12-12");

        return document;
    }

    //遍历
    public static void print(Document document){
        // 3)遍历
        //获取根节点
        Element root = document.getRootElement();
        System.out.println("根元素标签名"+root.getName());
        //获取子元素
        List<Element> list =  root.elements();
        //遍历子元素
        list.forEach(e->{
            System.out.println("标签名 : "+e.getName() + "-->id属性 = "+e.attributeValue("id"));
            //迭代所有子元素的迭代器
            Iterator<Element> it =  e.elementIterator();
            while(it.hasNext()){
                Element ele = it.next();
                System.out.println(ele.getName()+"---->"+ele.getData());
            }
        });
    }

    //加载xml文件 , 获取Docuemnt
    public static Document getDocument(String path) throws DocumentException {
        //1)创建流,加载xml文件
        SAXReader reader = new SAXReader();
        // 2)获取Document对象
        Document document = reader.read(new File(path));
        return document;
    }
}

2.4 修改与删除

2.4.1 XML文件
<?xml version="1.0" encoding="UTF-8"?>

<whl> 
  <whl1 id="1"> 
    <location>上海市浦东新区</location>  
    <date>2021-10-10</date>  
    <tuition>50000</tuition> 
  </whl1>  
  <whl2 id="2"> 
    <location>北京市朝阳区</location>  
    <date>2022-12-12</date> 
    <tuition>60000</tuition> 
  </whl2> 
</whl>

2.4.2 解析
public class Class002_XML {
    public static void main(String[] args) throws DocumentException, IOException {
        //writeToFile(update(getDocument("src/yjxxt.xml")),"src/yjxxt.xml");
        writeToFile(creatDocument(),"src\\whl.xml");

    }

    //修改与删除
    public static Document update(Document document){
        //1.找到id属性值为2的元素,删除子标签tuition
        Element root = document.getRootElement();
        List<Element> list = root.elements();
        list.forEach(e->{
            String idValue = e.attributeValue("id");
            if(idValue.equals("2")){
                //父节点.remove(子节点)
                Element removeElement = e.element("tuition");
                e.remove(removeElement);
            }
        });

        //2.找到shyjxxt,学费涨价1w
        Element shyjxxt = root.element("shyjxxt");
        Element tuition = shyjxxt.element("tuition");
        tuition.setData(Integer.parseInt(tuition.getText())+10000);
        return document;
    }


    //写出
    public static void writeToFile(Document document,String path) throws IOException {
        //1.  构建XMLWriter
        XMLWriter writer = null;
        //2.构建输出格式
        OutputFormat format = OutputFormat.createPrettyPrint();
        writer = new XMLWriter(new FileWriter(path),format);
        //3.写出
        writer.write(document);
        //4.刷出
        writer.flush();
        //5.关闭
        writer.close();
    }

    /*
        创建Document

        <yjxxt>
            <shyjxxt>
                <location>上海市浦东新区</location>
                <date>2021-10-10</date>
            </shyjxxt>
            <bjyjxxt>
                <location>北京市朝阳区</location>
                <date>2022-12-12</date>
            </bjyjxxt>
        </yjxxt>
     */
    public static Document createDocument(){
        //1.创建Document
        Document document = DocumentHelper.createDocument();
        //2.添加根元素
        Element root = document.addElement("yjxxt");
        //3.根元素中添加子元素
        Element shyjxxt = root.addElement("shyjxxt");
        Element bjyjxxt = root.addElement("bjyjxxt");

        shyjxxt.addElement("location").addText("上海市浦东新区");
        shyjxxt.addElement("date").addText("2021-10-10");
        bjyjxxt.addElement("location").addText("北京市朝阳区");
        bjyjxxt.addElement("date").addText("2022-12-12");

        return document;
    }

    //遍历
    public static void print(Document document){
        // 3)遍历
        //获取根节点
        Element root = document.getRootElement();
        System.out.println("根元素标签名"+root.getName());
        //获取子元素
        List<Element> list =  root.elements();
        //遍历子元素
        list.forEach(e->{
            System.out.println("标签名 : "+e.getName() + "-->id属性 = "+e.attributeValue("id"));
            //迭代所有子元素的迭代器
            Iterator<Element> it =  e.elementIterator();
            while(it.hasNext()){
                Element ele = it.next();
                System.out.println(ele.getName()+"---->"+ele.getData());
            }
        });
    }

    //加载xml文件 , 获取Docuemnt
    public static Document getDocument(String path) throws DocumentException {
        //1)创建流,加载xml文件
        SAXReader reader = new SAXReader();
        // 2)获取Document对象
        Document document = reader.read(new File(path));
        return document;
    }
}

3 XML文档的解析

3.1 理解

  • “形式良好”或“结构良好”的 XML 文档拥有正确的语法。合法的 XML 文档是“形式良好”的 XML 文档,并
    且遵循了特定的约束。
  • 在XML技术里,可以编写一个文档来约束一个XML文档的书写规范(与xml语法无关),这称之为XML
    约束。此举主要是为了保证数据的规范性和安全性。
  • DTD约束:语法简洁,功能比较单一。
  • Schema约束:语法复杂,功能比较强大。

3.2 DTD

  • DTD即文档类型定义-- Document Type Definition
  • 一个DTD文档可能包含如下内容
    • 元素的定义规则
    • 元素之间的关系规则
    • 属性的定义规则
3.2.1 内部导入
  • DTD约束和xml写在一个文件中。

    <?xml version="1.0" encoding="UTF-8" ?>
    <!--DTD约束-->
    <!DOCTYPE poem [
            <!ELEMENT poem (author,title+,content*) >
            <!ELEMENT author (#PCDATA)>
            <!ELEMENT title (#PCDATA)>
            <!ELEMENT content (#PCDATA)>
            ]>
    <poem>
        <author></author>
        <title></title>
    </poem>
    

    DTD菜鸟链接: link.

3.2.2 外部导入
  • 当验证的XML文件较多时,使用内部DTD可能出现冗余,此时可以通过引入dtd 文件进行xml 约束。
<!DOCTYPE mapper
PUBLIC "-//mybatis//DTD Mapper 3.0//EN"
"http://mybatis/dtd/mybatis-3-mapper.dtd">

3.3 Schema

  • Schema是用一套预先规定的xml元素和属性创建的,这些元素和属性定义了xml文档的结构和内容模
    式。Xml Shema规定xml文档实例的结构和每个元素/属性的数据类型。
  • 理解:对于Schema来讲,我们可以将shema比喻成为是表结构。在表结构里,定义一些数据的限制要
    求。然后我们xml文档就相当于是数据表将来要存储的数据,也就是数据库里面的数据表数据了,所以
    整体来讲的话schema它就是用于验证xml文档的。
  • schema文件本质上也是一个xml合法的文件。被别人约束xmlns:xs, 被 xmlns:xs 约束,同时还给了前
    缀。
  • schema文件又是对别的xml文件的约束,给自己里面定义的所有元素一个命名空间,为了让别人xml引
    入我当前定义的元素
    test.xsd
<?xml version="1.0" encoding="utf-8" ?>
<xs:schema xmlns:xs="http://www.w3/2001/XMLSchema"
           targetNamespace="http://www.myschema"
           xmlns="http://www.myschema"
           elementFormDefault="qualified">
<xs:element name="person">
    <xs:complexType>
        <xs:sequence>
            <xs:element name="id" type="xs:integer"/>
            <xs:element name="name" type="xs:string"/>
            <xs:element name="sex" type="xs:string"/>
            <xs:element name="address" type="xs:string"/>
        </xs:sequence>
    </xs:complexType>
</xs:element>
</xs:schema>

xmlns:xs="http://www.w3/2001/XMLSchema"
指定schema中用到的元素和数据类型都来自命名空间"http://www.w3/2001/XMLSchema"
同时它还规定了来自"http://www.w3/2001/XMLSchema"的元素和数据类型应该使用前缀xs:
targetNamespace="http://www.myschema"
显示被此schema定义的元素的命名空间为"http://www.myschema"
即id, name, sex, address都来自 "http://www.myschema" 命名空间
xmlns="http://www.myschema"
指定默认的命名空间为"http://www.myschema"
elementFormDefault="qualified"
指出任何XML实例文档所使用的且在此schema中声明过的元素必须被命名空间限定
<?xml version="1.0" encoding="utf-8" ?>
<person xmlns="http://www.myschema">
	<id>1</id>
	<name>admin</name>
	<sex></sex>
	<address>绿地伯顿</address>
</person>

Schema菜鸟链接: link.

本文标签: 正则XML