Java基础加强重温_13:XML(可拓展标记语言)、XML语法、XML约束、XML解析(Dom4j,JAXP)、Dom4j基本使用、Xpath表达式(XML路径语言)、XML解析综合案例

摘要

Java基础加强重温_13:
XML(可拓展标记语言、作用:小型数据库、框架配置文件、不同平台数据交换)、
XML语法(文档、标签/元素、属性、注释、转义字符、CDTA区)
XML约束(DTD约束:文档类型定义约束、Schema约束:XML模式定义约束)
XML解析(解析包:Dom4j,JAXP)、
Dom4j基本使用【Document对象(getRootElement)、Element对象(element(name),elements,elements(name))、Attribute对象(getName,getValue)】
Xpath表达式(XML路径语言、方法:selectNodes,selectSingleNodes、绝对路径表达式、相对路径表达式、全文搜索表达式、属性查找表达式)、
XML解析综合案例(传统getter/setter实现、反射实现)

一、XML介绍

1、什么是XML(可扩展标记语言)

1、英文全称extensible Markup Language,中文全称:可扩展标记语言
2、功能:用于各种组件或框架配置文件
3、标签组成:也是一种标记语言,文件内容由各种标签组成。

理解:
英文全称:extensible Markup Language
中文全称:可扩展标记语言,由一组标签(标记,元素)组成

1、XML与HTML的区别

HTML英文全称Hypertext Markup Language,也就是“超文本链接标记语言”,是用于在Internet上显示Web页面的主要标记语言。
在这里插入图片描述

2、XML的作用

XML在企业开发中主要有两种应用场景:
1、数据交换,用于不同的系统之间或不同的数据库之间进行数据交换。
XML本身是一个文本文件,可以在不同的系统之间展示数据。
2、用于各种框架的配置。如:下面是一个Spring框架配置文件:
在这里插入图片描述
理解:
XML的作用
1、可以作为一个小型数据库使用
2、用于框架的配置:作为配置文件使用(重点)
3、可以用于不同平台之间的数据交换

3、XML体验案例

需求

编写一个xml文档,用于描述人员信息,person代表一个人员,id是人员的属性代表人员编号。人员信息,包括age年龄、name姓名、sex性别信息。
效果:使用浏览器查看person.xml文件效果如下
在这里插入图片描述

实现步骤

1、使用idea在当前项目新建File,命名为person.xml(当前项目不是当前模块)
在这里插入图片描述
创建完成
在这里插入图片描述
2、编写person.xml 文件内容

<?xml version="1.0" encoding="UTF-8" ?> <!--这是一个人-->
<person id="110">
    <!--姓名-->
    <name>张三</name>
    <!--性别-->
    <sex/>
    <!--年年龄-->
    <age>20</age>
</person>

3、点击右上角的浏览器图标运行(IDEA自动集成的功能)
在这里插入图片描述

二、XML语法

XML语法包括七部分(第七已不使用)

1、文档声明
2、标签元素Element
3、属性Attribute
4、注释Comment
5、转义字符(实体字符)
6、字符数据区(用于显示大量的特殊字符的时候)
7、处理指令(不使用了)

1、文档声明

在这里插入图片描述
版本说明:W3C在1988年2月发布1.0版本, 2004年2月又发布1.1版本,因为1.1版本不能向下兼容1.0版本,所以1.1没有人用。在2004年2月W3C又发布了1.0版本的第三版。我们学习的还是1.0版本。

2、标签(元素)

在这里插入图片描述

标签命名规则

1、标签名区分大小写,比如<A>和<a>是不同的标签。
2、不能以数字开头,只能以中文,字母或下划线开头。
3、标签名不能包含空格,比如<name of>可以这样但是<name >不推荐。
4、标签名中不要使用冒号":",因为:是命名空间一个特殊的字符。

注意事项

1、一个XML文档中只能有一个根标签。
2、开始标签和结束标签必须成对出现。
3、一个标签中可以嵌套若干子标签,但是必须合理嵌套,不能交叉嵌套。
例如: <a>welcome to <b>www.itcast.cn</a></b>是错误的。

标签代码示例

<?xml version="1.0" encoding="UTF-8" ?>
<!--只能有一个根元素-->
<persons>
    <!--这是一个人-->
    <person id="110">
        <!--姓名-->
        <name>张三</name>
        
        <!--性别-->        
        <sex/>
        
        <!--年龄-->
        <age>20</age>
    </person>
    
    <!--这是一个人-->
    <person id="110">
        <!--姓名-->
        <name>张三</name>
        <!--性别-->
        <sex/>
        <!--年龄-->
        <age>20</age>
    </person>
</persons>

3、属性

在这里插入图片描述

4、注释

在这里插入图片描述

5、转义字符

XML中的转义字符与HTML一样。因为很多符号已经被文档结构所使用,所以在元素体或属性值中想使用这些符号就必须使用转义字符(也叫实体字符)
在这里插入图片描述

常见的XML转义字符

在这里插入图片描述

转义字符应用示例

需求

有一个<sql>标签,中间包含sql语句,查询所有年龄小于20岁的学生。

错误的写法(未使用转义字符代替符号)

出现无效的标签名

<sql>
    select * from student where age < 20 
</sql>

报错
在这里插入图片描述

正确写法(使用转义字符代替符号)
<sql>
    select * from student where age  &lt; 20 
</sql>

6、CDATA区(字符数据区)

可以让某些出现在XML文件中的字符不被XML解析器来解析,始终做为纯文本来操作。

为什么要使用字符数据区:
如果需要转义的字符太多,不方便给每个字符进行转义。
在这里插入图片描述

CDATA区示例

在这里插入图片描述

XML语法案例

<?xml version="1.0" encoding="utf-8"?>
<!--
    <?xml version="1.0" encoding="utf-8"?>
        version:xml语言版本
        encoding:设置当前XML文档使用的编码
        注意实现:必须出现在XML文档的第1行第1列

        标签命名规则
        - 标签名区分大小写,比如<A> 和<a>是不同的标签。
        - 不能以数字开头,只能以中文,字母或下划线开头。
        - 标签名不能包含空格,比如<name of> 但是可以这样<name > 不推荐。
        - 标签名中不要使用”:”,因为:是命名空间一个特殊的字符。

        注意事项
        - 一个XML文档中只能有一个根标签。
        - 开始标签和结束标签必须成对出现。
        - 一个标签中可以嵌套若干子标签,但是必须合理嵌套,不能交叉嵌套。
          - 例如:welcome to <b>www.itcast.cn</b>是错误的。
-->
<person gender='' >
    <!-- 有主体标签 -->
    <name>jack</name>
    <!-- 无主体标签-->
    <id />
    <books>
       <book>
          <name>java ee 入门</name>
       </book>
    </books>

    <sql>
        <!--
            转义字符:以&开头,以;结尾
            常用的转义字符:
                <   &lt;     less than
                >   &gt;     greater than
                "  &quot;
                '  &apos;
                &  &amp;
        -->
        select * from student where age &lt; 20;
        &gt; &quot;&apos;&amp;
    </sql>

    <!--
        CDATA区:字符数据区
            Character Data
            语法:<![CDATA[

                ]]>
            作用:能够保证数据原样输出,不会被解析
    -->
    <sql>
        <![CDATA[
            select * from student where age < 20 and score > 60;
        ]]>
    </sql>

</person>

XML存储数据案例

需求

给通讯录程序设计一个xml文件存储联系人的数据。联系人属性:编号、姓名、性别、电话、QQ、邮箱。
1、文件名: contact.xml
2、使用xml语法进行描述联系人信息。
3、能够存储多个联系人

示例代码1

<?xml version="1.0" encoding="UTF-8"?> 
<contactList>
    <contact id="S100">
        <name>潘金莲</name>
        <gender></gender>
        <phone>136909877890</phone>
        <qq>387439274</qq>
        <email>panpan@itcast.cn</email>
    </contact>
    <contact id="S200">
        <name>武大狼</name>
        <gender></gender>
        <phone>13609876543</phone>
        <qq>394535</qq>
        <email>wuda@itcast.cn</email>
    </contact>
    <contact id="X999" >
        <name>西蒙</name>
        <gender></gender>
        <phone>2987342394</phone>
        <qq>29342394</qq>
        <email>aaa@aa.com</email>
    </contact>
</contactList>

示例代码2

<?xml version="1.0" encoding="UTF-8" ?>
<!--
给通讯录程序设计一个xml文件存储联系人的数据。
联系人属性: 编号、 姓名、性别、电话、QQ、邮箱。
- 文件名:contact.xml
- 使用xml语法进行描述联系人信息
- 能够存储多个联系人
-->
<contacts>
    <contact id="100">
        <name>小泽</name>
        <gender></gender>
        <phone>10086</phone>
        <qq>10010</qq>
        <email>10010@qq.com</email>
    </contact>

    <contact id="110">
        <name>小泽2</name>
        <gender></gender>
        <phone>100186</phone>
        <qq>100101</qq>
        <email>100101@qq.com</email>
    </contact>
</contacts>

三、XML约束

因为XML是可扩展标记语言,可以写任意标记,所以我们需要对XML进行一些约束,让它只能出现哪些元素。某些元素下面只能出现哪些子元素,甚至可以指定某些元素的数据类型。从而保证XML文件数据正确性和有效性。

XML约束的作用

用来描述XML文档的结构。
让XML文件的书写更加规范。

XML约束的分类

XML约束有两种:DTD约束、schema约束

1、DTD约束(文档类型定义约束)

DTD约束,英文全称:Document Type Definition。中文名称:文档类型定义
作用:用来约束XML文件的,它本身是一个文本文件

DTD学习要求

在企业实际开发中,我们很少自己编写DTD约束文档,通常情况下通过框架提供的DTD约束文档编写XML文档。

DTD约束使用示例

步骤1:新建bookshelf.dtd文件

选择项目鼠标右键"NEW->File",文件名为"bookshelf.dtd"

步骤2:编写bookshelf.dtd文件

bookshelf.dtd文件内容如下

<!ELEMENT bookshelf (book+)>
<!ELEMENT book (title,author,price)> 
<!ELEMENT title (#PCDATA)>
<!ELEMENT author (#PCDATA)>
<!ELEMENT price (#PCDATA)> 
<!ATTLIST author
    性别 CDATA  #REQUIRED
    年龄 CDATA  #IMPLIED
    职务 CDATA  #FIXED "程序员"
    爱好 CDATA  "旅游" >

DTD文件解释
1、根元素是bookshelf,包含1个或多个book子元素,
2、 book这个子元素包含三个子元素(title,author,price)
3、 title, author, price子元素内容都是文本内容。
4、author元素中包括性别、年龄、职务、爱好等属性

步骤3:根据bookshelf.dtd编写XML文档

根据以上DTD文件约束编写一个符合约束的XML文档

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE bookshelf SYSTEM "bookshelf.dtd"> <bookshelf>
    <book>
        <title>JavaEE 开发教程</title>
        <author 性别="">Jack</author>
        <price>99.8</price>
    </book>
</bookshelf>
XML导入DTD文件格式

在这里插入图片描述

步骤4: idea检查xml约束合法性

在idea中,编写bookshelf.xml不符合制定的bookshelf.dtd约束会爆红
在这里插入图片描述

2、Schema约束(xml模式定义约束)

Schema约束即XSD(XML Schema Definition),翻译过来就是XML模式定义。
Schema约束是新的XML文档约束,功能更强大,数据类型更完善。要比DTD约束强大很多,是DTD约束的替代者。Schema本身也是XML文档,但Schema文档的扩展名为xsd,而不是xml。

DTD约束不能约束XML中数据的类型,功能上比较简单。Schema约束功能更加强大,可以约束数据的类型,使用相对复杂。Schema约束慢慢的会代替DTD约束。

Schema约束的根元素、文档概念、命名空间

根元素

Schema约束文件本身也是XML文件,所以也有根元素,根元素的名字叫:schema

文档概念

Schema约束的文档
模式文档:制定约束的XML文档(类似于:类)。即Schema约束文件
实例文档:被约束的XML文档(类似于:对象)。即使用Schema约束的xml文件
一个实例文档是可以有多个模式文档进行约束的
在这里插入图片描述

命名空间(解决多模式文档约束的标签命名冲突问题)

Schema约束的命名空间与Java中的包是同一用途。如果每个元素和属性都有自己的名称空间,那么就不会出现名字冲突问题,就像是每个类都有自己所在的包一样,那么类名就不会出现冲突。

命名空间作用
用来声明实例文档中使用的标签被哪个schema文件(模式文档)约束。
用来避免元素(标签)和属性命名冲突。

命名空间的定义

定义位置:在模式文档的根元素的开始标签之中,也就是在schema标签中。
定义格式:

targetNamespace="命名空间名"

须知:命名空间名一般是:”URI地址”字符串,比如:” http://www.itheima.com/a”。URI地址不会被解析器用于查找信息,其唯一的作用就是赋予命名空间一个唯一的名称。如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema" 
	targetNamespace="http://www.ithema.com/a"  
	elementFormDefault="qualified">
</schema>

targetNamespace=“http://www.ithema.com/a” 就是定义命名空间,名称为:http://www.ithema.com/a,相当于java的包名。

命名空间的使用(引入)

在xml文件中引入,引入命名空间就相当于Java中的导包操作

引入的位置:在实例文档根元素的开始标签之中。
引入的格式

xmlns:前缀=“URI地址”或 xmlns="URI地址"

引入示例和解析说明如下

<?xml version="1.0" encoding="UTF-8"?>
<note xmlns="http://www.itheima.com/a" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:schemaLocation="http://www.itheima.com/a note.xsd ">
</note>

xmlns = “http://www.itheima.com/a”
引入自定义的命名空间,使用默认的命名空间。
xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance”
引入官方定义的命名空间,使用了前缀xsi,则表示在该实例文档中使用来自该命名空间中定义的元素时需要带上前缀xsi访问。

注意事项
1、没有指定前缀称为默认的命名空间。在访问默认命名空间中定义的元素时不需要带前缀访问。访问非默认命名空间的元素时必须带前缀访问。
2、一个XML文档中只能有一个默认的命名空间。

Schema学习要求

虽然schema功能比dtd强大,但是编写要比DTD复杂,同样以后我们在企业开发中也很少会自己编写schema文件。我们只需要借助开发工具,在现有的xsd约束下,写出正确的xml文件即可。

Schema约束使用示例

步骤1:新建schema约束文件books.xsd(本质也是一个xml文件)

新建schema约束文件books.xsd,对售价约束数据类型,代码如下。

<?xml version="1.0" encoding="UTF-8"?>
    <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
  targetNamespace="http://www.itheima.com/book" elementFormDefault="qualified">
  <!-- 根元素是bookselft,包含子元素,所以是复杂类型 -->
  <xs:element name="bookshelf">
    <xs:complexType>
      <!-- book出现1~n次 -->
      <xs:sequence minOccurs="1" maxOccurs="unbounded">
        <!-- book因为包含子元素和属性,所以也是复杂元素 -->
        <xs:element name="book">
          <!-- 元素要依次出现 -->
          <xs:complexType>
            <xs:sequence>
              <!-- 其它元素都是简单元素 -->
              <xs:element name="title" type="xs:string"/>
              <xs:element name="author" type="xs:string"/>
              <xs:element name="price" type="xs:positiveInteger"/>
            </xs:sequence>
            <!-- 属性要写在最后,这里表示属性必须 -->
            <xs:attribute name="isbn" use="required"/>
          </xs:complexType>
        </xs:element>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

此xsd文件的解释:
1、根元素是bookshelf
2、bookshelf中的子元素book可以出现多次
3、book中依次出现三个子元素:title,author,price
4、book中有一个属性: isbn

步骤2:新建books.xml,使用schema约束文件

xml引入schema约束语法:

<根元素 xmlns="命名空间" 
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="命名空间 xsd 约束⽂文件名"> </根元素>

books.xml内容:

<?xml version="1.0" encoding="utf-8"?>
<bookshelf xmlns="http://www.itheima.com/book"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.itheima.com/book books.xsd">
    <book isbn="SB100">
        <title>Java基础教程</title>
        <author>rose</author>
        <price>66</price>
    </book>
</bookshelf>
步骤3:idea检查xml约束合法性

在这里插入图片描述

四、XML解析

当将数据存储在XML后,我们就希望通过程序获取XML的内容。如果我们使用Java基础所学的IO知识是可以完成的,不过要非常繁琐的操作才可以完成,所以会使用专门的工具来解析XML。

1、XML解析方式

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

DOM解析
概述:一次性将整个xml文档加载到内存中,并在内存中生成一颗DOM树。
优点:可以对树上的元素(节点)进行增删改查操作
缺点:如果xml文档较大,则会占据很多内存

SAX解析
概述:从上往下解析,解析一行释放一行
优点:占据内存少
缺点:只能以只读方式解析,不能执行增删改操作
在这里插入图片描述

2、常用的解析开发包

JAXP:Oracle公司提供支持DOM和SAX开发包
Dom4j:比较简单的的解析开发包,将整个XML加载到内存中做为一棵DOM树。

3、DOM解析原理及结构模型(Dom4j)

原理:XML DOM和HTML DOM一样, XML DOM将整个XML文档加载到内存,生成一个DOM树,并获得一个Document对象,通过Document对象就可以对DOM进行操作。

xml文件
在这里插入图片描述
DOM树结构模型
在这里插入图片描述

4、DOM树的组成元素

在这里插入图片描述
Dom树的组成元素

Node  节点  
	Dom树上的每一个对象都是Node对象
	
Document 文档对象 
	每一个XML文件加载到内存中都会对应一个Document
	
Element  元素(标签或标记)对象,
	树上每一个标签都是Element对象
	
Attribute  属性对象,
	标签中每一个属性都是Attribute对象
	
Text  文本对象   
	每个标签体内容都是Text对象

XML中Element,Node,Attr的区别和联系
https://blog.csdn.net/u011559849/article/details/22983317

五、Dom4j基本使用

采用DOM方式来解析XML文件

Dom4j使用步骤
1、去官网下载zip包。http://www.dom4j.org
2、解压dom4j-1.6.1.zip
3、在项目中创建一个文件夹: lib
4、将dom4j-1.6.1.jar文件复制到lib文件夹
5、在Jar文件上点右键,选择Add as Library->点击OK
6、在类中导包使用

数据准备:创建XML文件contact.xml

在项目中或模块下创建一个XML文件,命名为:contact.xml,内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<contactList>
    <contact id="S100" vip="true">
        <name>潘金莲</name>
        <gender></gender>
        <phone>136909877890</phone>
        <qq>387439274</qq>
        <email>panpan@itcast.cn</email>
    </contact>
    <contact id="S200">
        <name>武大狼</name>
        <gender></gender>
        <phone>13609876543</phone>
        <qq>394535</qq>
        <email>wuda@itcast.cn</email>
    </contact>
    <contact id="X999" >
        <name>西蒙</name>
        <gender></gender>
        <phone>2987342394</phone>
        <qq>29342394</qq>
        <email>aaa@aa.com</email>
    </contact>
</contactList>

1、获得Document对象

一个XML文件加载到内存中时就会创建一个Document对象,该Document对象包含了了XML中的所有
节点内容,通过该对象就可以获得对应XML文件的所有内容。

Document对象常用方法

在这里插入图片描述

代码示例1(获得Document对象)

读取XML文档并获取Document对象

/**
* 使用 dom4j 解析工具读取 xml 文件
*/ 
public class Demo1 {
    public static void main(String[] args) { 
        try {
            // 1. 创 建 SAXReader( 解 析 器 对 象 ) 
            SAXReader reader = new SAXReader();
            // 2.调用 read 方法,读取 xml 文件
            Document doc = reader.read("contact.xml"); 
            System.out.println(doc);
        } catch (DocumentException e) { 
            e.printStackTrace();
        }
    }
}

代码示例2(获得xml根元素对象)

需求:获得xml根元素对象并输出到控制台

实现步骤
1. 创建XML解析器对象
2. 调用解析器对象的方法读取XML文档并获取Document对象

public static void main(String[] args) throws DocumentException {
    // 1.得到文档对象
    SAXReader reader = new SAXReader();
    Document document = reader.read("contact.xml");
    // 2.得到根元素
    Element root = document.getRootElement();
    // 3.打印输出
    System.out.println(root)
}

小结

如何获得Document对象
1、创建XML解析器对象
SAXReader reader = new SAXReader();

2、调用解析器对象的read方法:传递文件对象(关联要解析的xml文档)
Document document = reader.read(new File(“xml文档路径”));

Document对象常用方法
Element rootElement = getRootElement();

2、获得Element对象

DOM树上的每一个标签都是一个Element对象。每一个Elment对象都是Node的子类。

Element常用方法(element(name)、elements、elements(name))

在这里插入图片描述
空格、换行、制表符:也是属于文本的一部分,在解析xml文件的时候要注意处理。

代码示例

需求1:获得所有的contact子元素对象。
需求2:获得contact元素下所有的子元素对象
需求3:输出所有contact元素下子元素的文本内容

package com.itheima._02dom4j;

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

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

/**
  目标:获取Element对象并通过Element对象获取元素名称和元素的文本内容

  需求:
 - 需求1:获得所有的contact⼦元素对象
 - 需求2:获得contact元素下所有的子元素对象
 - 需求3:输出所有contact元素下子元素的⽂本内容

 */
public class Demo02 {
    public static void main(String[] args) throws Exception{
        // 1. 创建XML解析器对象
        SAXReader reader = new SAXReader();
        // 2. 调用解析器对象的方法读取XML文档并获取Document对象
        Document document = reader.read(new File("day13_课堂代码/contacts.xml"));
        // 3. 获得根元素对象
        Element rootElement = document.getRootElement();

        // 获得根元素下第一个contact子元素对象
        System.out.println(rootElement.element("contact"));

        // - 需求1:获得所有的contact⼦元素对象
        List<Element> contactElements = rootElement.elements("contact");
        for (Element contactElement : contactElements) {
            System.out.println("=============>" + contactElement.elementTextTrim("name"));
            // - 需求2:获得contact元素下所有的子元素对象(name、gender、phone...)
            List<Element> childElements = contactElement.elements();
            for (Element childElement : childElements) {
                // System.out.println(childElement);
                // - 需求3:输出所有contact元素下子元素的⽂本内容

                // String类trim()方法:去除字符串左右两边的空格
                // "  abc  ".trim() ==> "abc"
                //  Integer.parseInt(" 100 ".trim());
                // System.out.println("abc".trim());

                // 获得标签名称
                String name = childElement.getName();
                // 获得标签体内容
                String text = childElement.getTextTrim();
                System.out.println(name+"="+text);
            }
        }
    }
}

3、获得Attribute对象

DOM树上每一个元素的属性都是一个Attribute对象,每一个Attribute对象都是Node的子类。
获得Attribute对象前提:先获得元素Element对象,调用Element对象与属性相关的方法。

Attribute常用方法(Attribute对象方法)

在这里插入图片描述

Element中与属性相关方法(Element对象方法,与Attribute对象相关的方法)

在这里插入图片描述

代码示例

获取Attribute对象并通过Attribute对象获取属性名和属性值

需求1:使用2种方式,得到contact上id属性值
通过属性名获得attribute对象,再用attribute对象获得属性值
通过属性名直接获得属性值

需求2:在contact元素上添加一个vip的属性值为true/false
得到contact上所有的属性名和属性值

public class AttributeDemo01 {
    public static void main(String[] args)throws Exception{
        // 1. 创 建 SAXReader( 解 析 器 对 象 )
        SAXReader reader = new SAXReader();
        // 2.调用 read 方法,读取 xml 文件
        Document doc = reader.read("day26_dom4j/contact.xml");
        // 3.得到根元素
        Element root = doc.getRootElement();
        // 需求1:获得所有的contact子元素对象
        List<Element> contacts = root.elements("contact");
        for (Element contact : contacts) {
            // ⽅方式1:得到contact上id属性值
            Attribute idAttr = contact.attribute("id");
            System.out.println(idAttr.getName()+"="+idAttr.getValue());

            // ⽅方式2:得到contact上id属性值
            String id = contact.attributeValue("id");
            System.out.println(id);
        }
        System.out.println("-------得到contact上所有的属性名和属性值 --------");
        for (Element contact : contacts) {
            // 获得contact元素上的所有属性
            List<Attribute> attributes = contact.attributes();
            // 遍历输出属性名和属性值
            for (Attribute attr : attributes) {
                System.out.println(attr.getName()+"="+attr.getValue());
            }
            System.out.println("-----------------");
        }
    }
}

六、XML路径语言(Xpath表达式)

XPath即为XML路径语言:XML Path Language

作用:XPath使用路径表达式来选取HTML或XML文档中的元素节点或属性节点。

dom4j与Xpath相关的方法(selectSingleNodes、selectNodes)

在这里插入图片描述

Xpath表达式语法分类

1、绝对路径表达式
2、相对路径表达式
3、全文搜索表达式
4、属性查找表达式

1、绝对路径表达式

从文档对象、根元素、…一级一级往下找
理解:文档对象相当与盘符
在这里插入图片描述

代码示例

需求:采用绝对路径获取方式,从根节点开始逐层查找/contactList/contact/name/节点列表并打印信息
实现步骤
1、创建XML解析器对象
2、读取XML文档并获得Document对象
3、定义xpath表达式: /contactList/contact/name/
4、调用Document对象的selectNodes方法执行xpath获得节点集合
5、遍历输出每个节点

public class XPathDemo01 {
    // 绝对路径表达式
    @Test
    public void test01()throws Exception{
        // 创建xml解析器对象
        SAXReader saxReader = new SAXReader();
        // 获得文档对象
        Document document = saxReader.read("contact.xml");
        // Xpath表达式:绝对路径表达式
        String xpath = "/contactList/contact/name";
        // 使用Xpath查找节点
        List<Node> list = document.selectNodes(xpath);
        // 遍历输出
        for (Node node : list) {
            System.out.println(node);
        }
    }
}

2、相对路径表达式

在这里插入图片描述

代码示例

需求:先采用绝对路径获取contactList节点,再采用相对路径获取下一级contact节点的name子节点并打印信息。

实现步骤:
1、创建XML解析器对象
2、读取XML文档并获得Document对象
3、定义Xpath表达式: /contactList
4、调用Document对象的selectsingleNode方法,执行Xpath获得根节点对象
5、通过根节点对象调用selectNodes方法,执行相对路径表达式: ./contact/name
6、打印输出所有的节点

public class XPathDemo02 {
    // 相对路径表达式
    @Test
    public void test02()throws Exception{
        // 创建xml解析器对象
        SAXReader saxReader = new SAXReader();
        // 获得文档对象
        Document document = saxReader.read("contact.xml");
        // 绝对路径表达式
        String xpath = "/contactList";
        // 使用Xpath查找节点
        Element rootElement = (Element) document.selectSingleNode(xpath);
        System.out.println(rootElement);
        // 相对路径表达式:查询rootElement节点下所有name子节点
        List<Node> contactNodes = rootElement.selectNodes("./contact/name");
        for (Node node : contactNodes) {
            System.out.println(node);
        }

3、全文搜索表达式

在这里插入图片描述

全文搜索表达式示例

在这里插入图片描述

代码示例1

需求:直接全文搜索所有的contact节点并打印代码

public class XPathDemo03 {
     // 全文搜索表达式
    @Test
    public void test03() throws Exception{
        // 创建xml解析器对象
        SAXReader saxReader = new SAXReader();
        // 获得文档对象
        Document document = saxReader.read("contact.xml");
        // Xpath表达式: // 表示全文搜索,不管在哪一级
        String xpath = "//contact";
        // 使用Xpath查找节点
        List<Node> nodes = document.selectNodes(xpath);
        for (Node node : nodes) {
            System.out.println(node);
        }
    }
}

代码示例2

package com.itheima._03xpath;

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

import java.util.List;

/**
  目标:使用xpath全文搜索路径查询元素
  需求:直接全文搜索所有的 contact节点并打印
 */
public class Demo03 {
    public static void main(String[] args) throws Exception {
        // 创建XML解析器对象并获得Document对象
        Document document = new SAXReader().read("day13_课堂代码/contacts.xml");
        // 定义全文搜索表达式路径
        // String xpath = "//contact";
        // String xpath = "//contact/name";
        String xpath = "//contact//name";
        // 根据全文搜索表达式路径查询元素
        List<Element> contactElements = document.selectNodes(xpath);
        for (Element contactElement : contactElements) {
            System.out.println(contactElement);
        }
    }
}

4、属性查找表达式

在这里插入图片描述

代码示例

需求:
1、查找所有id属性节点
2、查找包括id属性的contact元素
3、查找包括id属性且属性名为S100的contact元素
4、查找不包含vip属性的contact节点代码

package com.itheima._03xpath;

import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;

import java.util.List;

/**
  目标:使用Xpath表达式查找属性
  需求:
     1. 查找所有id属性节点
     2. 查找包括id属性的contact元素
     3. 查找包括id属性且属性名为S100的contact元素
     4. 查找不包含vip属性的contact节点
 */
public class Demo04 {
    public static void main(String[] args) throws Exception {
        // 创建XML解析器对象并获得Document对象
        Document document = new SAXReader().read("day13_课堂代码/contacts.xml");
        // 定义路径表达式
        //  1. 查找所有id属性节点
        String xpath01 = "//@id";
        // 根据路径表达式查询
        List<Attribute> idAttrs = document.selectNodes(xpath01);
        for (Attribute idAttr : idAttrs) {
            System.out.println(idAttr.getName()+"="+idAttr.getValue());
        }
        System.out.println("----------------------------------");
        // 2. 查找包括id属性的contact元素
        String xpath02 = "//contact[@id]";
        List<Element> contactElements = document.selectNodes(xpath02);
        for (Element contactElement : contactElements) {
            System.out.println(contactElement);
        }
        //  3. 查找包括id属性且属性名为S100的contact元素
        System.out.println("-----------------------------------");
        String xpath03 = "//contact[@id='S100']";
        Node node = document.selectSingleNode(xpath03);
        System.out.println(node);

        System.out.println("-----------------------------------");
        // 4. 查找不包含vip属性的contact节点
        String xpath04 = "//contact[not(@vip)]";
        List list = document.selectNodes(xpath04);
        System.out.println(list);
    }
}

七、XML解析综合案例

需求

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

数据准备

在项目下创建contact.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<contactList>
	<contact id="100" vip="true">
		<name>潘金莲</name>
		<gender></gender>
		<phone>136909877890</phone>
		<qq>387439274</qq>
		<email>panpan@itcast.cn</email>
	</contact>
	<contact id="200" vip="false">
		<name>武大狼</name>
		<gender></gender>
		<phone>13609876543</phone>
		<qq>394535</qq>
		<email>wuda@itcast.cn</email>
	</contact >
	<contact id="999">
		<name>西蒙</name>
		<gender></gender>
		<phone>2987342394</phone>
		<qq>29342394</qq>
		<email>aaa@aa.com</email>
	</contact>
</contactList>

Contact类

package com.itheima._04xml解析综合案例;

public class Contact {
    private int id;
    private String name;
    private String gender;
    private String email;
    private String qq;
    private String phone;
    private boolean vip;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getQq() {
        return qq;
    }

    public void setQq(String qq) {
        this.qq = qq;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    public boolean isVip() {
        return vip;
    }

    public void setVip(boolean vip) {
        this.vip = vip;
    }

    @Override
    public String toString() {
        return "Contact{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", gender='" + gender + '\'' +
                ", email='" + email + '\'' +
                ", qq='" + qq + '\'' +
                ", phone='" + phone + '\'' +
                ", vip=" + vip +
                '}';
    }
}

代码实现

package com.itheima._04xml解析综合案例;

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

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

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

    实现步骤
        1. 读取XML文档获得Document对象
        2. 定义xpath表达式:查询所有contact元素
        3. 创建集合对象:用来存储Contact对象
        4. 遍历contact元素:每遍历一个Contact元素就创建一个Contact对象
        5. 给Contact对象的成员变量赋值
        6. 将Contact对象添加到集合中
        7. 遍历输出Contact对象
 */
public class Demo01 {
    public static void main(String[] args) throws Exception{
        // 1. 读取XML文档获得Document对象
        Document document = new SAXReader().read("day13_课堂代码/contacts.xml");
        // 2. 定义xpath表达式:查询所有contact元素
        String xpath = "//contact";
        // 3. 创建集合对象:用来存储Contact对象
        ArrayList<Contact> contacts = new ArrayList<>();
        // 4. 遍历contact元素
        List<Element> contactElements = document.selectNodes(xpath);
        for (Element contactElement : contactElements) {
             // contactElement代表contact元素
            //  4.1 创建一个Contact对象
            Contact contact = new Contact();

            contact.setId(Integer.parseInt(contactElement.attributeValue("id")));
            contact.setVip(Boolean.parseBoolean(contactElement.attributeValue("vip")));

			//方式1,传统getter/setter实现
            //  4.2 给Contact对象的成员变量赋值
           /* contact.setName(contactElement.elementTextTrim("name"));
            contact.setGender(contactElement.elementTextTrim("gender"));
            contact.setPhone(contactElement.elementTextTrim("phone"));
            contact.setQq(contactElement.elementTextTrim("qq"));
            contact.setEmail(contactElement.elementTextTrim("email"));*/

			//方式2,反射实现
            // 获得Class对象
            Class c = contact.getClass();
            // 获得当前contact元素下的所有子元素对象
            List<Element> childElements = contactElement.elements();
            // 遍历子元素集合
            for (Element childElement : childElements) {
                 // 获得元素名称
                String name = childElement.getName(); // "name"  "gender" ...
                // 获得元素内容
                String text = childElement.getTextTrim(); // "潘金莲" "女"
                // 根据成员变量名获得Field对象
                Field field = c.getDeclaredField(name);
                // 暴力反射
                field.setAccessible(true);
                // 给对象contact的成员变量赋值为text
                field.set(contact, text);
            }
            //  4.3.将Contact对象添加到集合中
            contacts.add(contact);
        }

        // 7. 遍历输出Contact对象
        for (Contact contact : contacts) {
            System.out.println(contact);
        }
    }
}
  • 0
    点赞
  • 0
    收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:数字20 设计师:CSDN官方博客 返回首页
评论

打赏作者

Jinniu00

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值