12----xml文件+xml文件的解析(dom4j包)


typora-root-url: img
typora-copy-images-to: img

《XML&Dom4j-笔记》

学习目标

  1. 能够说出 XML 的作用
  2. 了解 XML 的组成元素
  3. 能够说出有哪些 XML约束技术
  4. 能够说出解析 XML 文档 DOM方式原理
  5. 能够说出Dom4j常用的类
  6. 能够通过Dom4j得到文档对象(重点)
  7. 能够读取Dom树上的元素对象(重点)
  8. 能够使用 XPath 解析 XML 文档

学习内容

XML概述

目标

  1. 能够说出XML的概念
  2. 能够编写第1个XML文件

什么是XML

  1. 英文:Extensible Markup Language 可扩展标记语言
  2. 标记语言:整个文档由各种标记组成
  3. 可扩展:所有的标签都是自定义的,可以随意扩展的。如:,<姓名>, <你喜欢>, <凤姐>

XML作用

  1. 数据交换:不同的计算机语言之间,不同的操作系统之间进行数据交换。[外链图片转存失败(img-RRYPtfVU-1564584747336)(/1552221268464.png)]

  2. 配置文件:在后期我们主要用于各种框架的配置文件。以前接触过的XML文件。c3p0-config.xml

[外链图片转存失败(img-OFRuKzoc-1564584747343)(/1552221310087.png)]

案例:编写第1个XML文件

​ 编写xml文档,用于描述人员信息,person代表一个人员,id是人员的属性代表人员编号。人员信息包括age年龄、name姓名、sex性别信息。

效果

[外链图片转存失败(img-W478w4Is-1564584747346)(/1552352318788.png)]

步骤

  1. 选择当前项目鼠标右键新建

[外链图片转存失败(img-o6qHuN1y-1564584747347)(/1552221478628.png)]

  1. 编写person.xml文件

    
    <person id="1">
        <name>张三name>
        <age>18age>
        <sex>sex>
    person>
    
  2. 通过浏览器解析XML的内容

    [外链图片转存失败(img-nMIk8mSZ-1564584747348)(/1552221534649.png)]

  • 注:XML以后通过Java来进行解析,很少直接在浏览器上显示。

小结

  1. 什么是XML?
    可扩展的标记语言, 由很多的标签组成
  2. XML主要有哪两个作用?
    数据交换
    配置文件

XML的组成:声明和元素

目标

  1. 学习XML中7种组成部分
  2. 学习XML中文档声明和元素的作用

XML由七种组成元素构成

  1. 文档声明

  2. 标签/元素

  3. 属性

  4. 注释

  5. 实体字符

  6. CDATA 字符数据区

  7. 处理指令

[外链图片转存失败(img-IXOWsS1e-1564584747350)(/1564364470119.png)]

文档声明

1.文档声明格式


作用: 告诉打开这个文件的软件,这是一个XML文件.

注意:

结尾
必须放在第一行

声明的三种属性

文档声明的三个属性 说明
version 指定XML文件使用的版本,取值是1.0
encoding 当前XML文件使用的编码(字符集) UTF-8/GBK
standalone 指定当前这个XML文件是否是一个独立的文件,省略的,默认是独立文件。

版本说明

​ W3C在1988年2月发布1.0版本,2004年2月又发布1.1版本,因为1.1版本不能向下兼容1.0版本,所以1.1没有人用。在2004年2月W3C又发布了1.0版本的第三版。我们学习的还是1.0版本。

元素

元素就是标签

元素语法格式

<元素名>内容

<元素名>: 起始标签
: 结束标签

没有内容的标签可以省略
<元素名>	-> <元素名/>

XML标签命名的要求

  1. 严格区分大小写: 不行
  2. 标签名不能以数字开头,只能以字母或下划线开头,可以是中文: <9miao>不行
  3. 标签名不能包含空格: 不行

根标签

没有其他标签包含的就是根标签

在一个xml文档中,只允许有一个根标签

代码


<persons>
    
    <person id="1">
        <name>张三name>
        <age>18age>
    person>

    <person id="2">
        <name>李四name>
        <age>19age>
    person>
persons>

小结

  1. 文档声明有哪两个常用的属性?
    version: 表示版本号
    encoding: 指定文件的编码
  2. 一个XML有几个根元素?
    一个

XML的组成:属性

目标

学习XML文档中属性格式

属性语法格式

<元素名 属性名="属性值">元素名>

注意

  1. 属性放在开始标签中
  2. 属性值必须放在双引号或单引号中
  3. 在一个标签中,属性可以有多个,但不能出现同名的属性

小结

1.说出属性语法格式?

<元素名 属性名="属性值">元素名>

XML的组成:注释

目标

学习ML文档中的注释格式

注释语法格式


注释作用

给程序员看的

快捷键

注释: ctrl + /

嵌套

在XML中注释不能嵌套

小结

1.说出注释语法格式?


XML的组成:实体字符

目标

学习XML文档中实体字符的使用

因为很多符号已经被文档结构所使用,所以在元素体或属性值中想使用这些符号就必须使用实体字符

[外链图片转存失败(img-7OhqkiBe-1564584747352)(/1552353386585.png)]

语法

[外链图片转存失败(img-Fo5gj08y-1564584747353)(/1556375355138.png)]

规律

所有的实体字符都是以 &开头, 以;结尾 &xxx;

需求

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

效果

[外链图片转存失败(img-KM9L8gaD-1564584747355)(/1552353485579.png)]

错误写法


    
    select * from user where age < 20

正确写法

<sql>
    
    select * from user where age < 20
sql>

小结

  1. 为什么要有实体字符?

    因为XML中已经使用了很多符号,我们就不能够使用,使用实体字符代替

XML的组成:字符数据区

目标

学习字符数据区CDATA使用

为什么要字符数据区

​ 如果大量使用实体字符,会导致XML可读性降低。另一种解决方案:可以使用字符数据区包裹这些字符,只要在字符数据区中的内容,XML解析器会以纯文本进行解析。

CDATA字符数据区格式

[外链图片转存失败(img-QuNmdZYu-1564584747356)(/1552225954936.png)]

记忆

<>





CDATA字符数据区作用

放在CDATA区中的内容会原样输出

小结

CDATA字符数据区作用?

里面的内容看作普通的内容会原样显示

XML的组成:处理指令

目标

了解处理指令的使用

使用处理指令

 相当于java中的导包,引入约束


小结

一个XML有哪7个组成部分?

  1. 文档声明
  2. 处理指令
  3. 元素/标签
  4. 属性
  5. 实体字符
  6. CDATA字符数据区
  7. 注释

XML约束:DTD约束

目标

了解XML中的两种约束

了解DTD约束

XML为什么要有约束

因为XML文件的标签和属性可以随意扩展,有时我们必须要限制每个文档有哪些元素,每个元素有哪些子元素,每个元素有哪些属性,属性的值是什么类型等。

通过XML约束可以保证XML文件中的数据的正确性


<person>
	<name>凤姐name>
	<age>20age>
person>

XML的两种约束

  1. DTD约束(简单,弱)
  2. Schema约束(复杂,强)

DTD约束的概念

  1. DTD概念: Document Type Definiation 文档类型定义
  2. DTD作用:约束XML中只能出现某些数据
导入DTD文件的两种格式 说明
根元素 SYSTEM “DTD文件”> 本地的约束,适合个人,公司小范围的使用的约束
根元素 PUBLIC “文件描述” “DTD文件”> 网络上的约束,适合大范围的使用

如:hibernate框架的导入方式

[外链图片转存失败(img-hC5ofTuC-1564584747358)(/1552227668343.png)]

DTD使用案例

步骤1:新建bookshelf.dtd文件,选择项目鼠标右键“NEW->File",文件名为“bookshelf.dtd”

步骤2:复制下面内容到bookshelf.dtd






步骤3:新建books.xml,代码如下



<书架>
    <>
        <书名>JavaEE SSM书名>
        <作者>张三作者>
        <售价>30售价>
    >
    <>
        <书名>人鬼情喂鸟书名>
        <作者>李四作者>
        <售价>300售价>
    >
书架>

步骤4:idea开发工具books.xml的dtd约束验证不通过的效果

[外链图片转存失败(img-1ysYD625-1564584747359)(/1552355976703.png)]

DTD学习要求

​ 在企业实际开发中,很少自己编写DTD约束文档,我们后期只需通过框架提供的DTD约束文档编写出相应的XML配置文档。

小结

  1. DTD的作用是什么?

    约束XML中只能出现某些内容

XML约束:Schema约束

目标

了解Schema约束

为什么要有Schema约束

DTD的不足:

  1. 不能验证数据类型
  2. 因为DTD是一个文本文件,本身不能验证是否正确。

[外链图片转存失败(img-Ev6Ztt3e-1564584747361)(/1552302664354.png)]

Schema约束文件扩展名(XML Schema Definition)XML模式定义:xsd

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

模式文档和实例文档

模式文档:就是Schema约束文档

实例文档:就是我们要写的XML

[外链图片转存失败(img-yrSfAKgF-1564584747363)(/1557066139347.png)]

命名空间

问:如果在Java中如果使用同名的类,如何避免冲突?比如:Date类,在java.util和java.sql包中都有
package com.itheima;
import java.sql.Date;
public class Demo1 {
    public static void main(String[] args) {
        // java.util.Date
        // java.sql.Date

        java.util.Date d1 = new java.util.Date();
        System.out.println(d1);

        java.sql.Date d2 = new java.sql.Date(System.currentTimeMillis());
        System.out.println(d2);
    }
}
如果不同的xsd约束文件出现同名的标签,如何避免冲突?

一个XML文件可以有多个约束文件,不同的Schema约束文档中出现相同的内容.给不同的Schema文档取不同的命名空间,通过命名空间可以区分使用的是哪个Schema里面的约束

[外链图片转存失败(img-cOoWZNob-1564584747364)(/1557067140710.png)]

  1. targetNamespace用来指定命名空间
  2. 默认命名空间,前面不需要指定前缀,直接使用<标签名>
  3. 一个XML文档中只能有一个默认的命名空间
  4. 其它命名空间中的标签,使用<前缀:标签名>来引用

Schema演示案例

  1. 步骤1:新建schema约束文件bookshelf.xsd,复制以下代码到bookshelf.xsd文件中:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
           targetNamespace="http://www.itcast.cn"
           elementFormDefault="qualified">
    <xs:element name='书架'>
        <xs:complexType>
            <xs:sequence maxOccurs='unbounded'>
                <xs:element name=''>
                    <xs:complexType>
                        <xs:sequence>
                            <xs:element name='书名' type='xs:string'/>
                            <xs:element name='作者' type='xs:string'/>
                            <xs:element name='售价' type='xs:double'/>
                        xs:sequence>
                    xs:complexType>
                xs:element>
            xs:sequence>
        xs:complexType>
    xs:element>
xs:schema>

注意:在上面的schema约束文档中我们只需要关注targetNamespace=“http://www.itcast.cn”,就是命名空间相当于知道了包名
2. 步骤2:新建books2.xml使用schema约束文件

在自己编写的XML中引入schema约束文件的格式

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

book2.xml


<书架 xmlns="http://www.itcast.cn" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://www.itcast.cn bookshelf.xsd">
    <>
        <书名>JavaEE书名>
        <作者>张三作者>
        <售价>39售价>
    >
    <>
        <书名>西游记书名>
        <作者>吴承恩作者>
        <售价>3000售价>
    >
书架>
  1. 步骤3:违反约束,开发工具提示效果

    [外链图片转存失败(img-HCBYq4zQ-1564584747366)(/1552357355473.png)]

Schema学习要求

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

<提示 -> 回车 -> 自动补全

小结

  1. XML有哪两种约束?
    1. DTD约束(弱)
    2. Schema约束(强大)
  2. Schema约束相比DTD有哪些优点?
    1. Schema约束类型更加详细
    2. 一个XML可以引入多个Schema约束
    3. Schema约束本类就是以XML,受官方的约束,不容易写错

XML的两种解析方式

目标

了解XML的解析方式有哪两种

什么是XML的解析

使用Java语言去解析XML文件,读取XML中的元素,属性,文本等数据。

两种解析方式

  1. DOM解析
  2. SAX解析

SAX解析

  • 优点:事件驱动型解析方式,读取一行就解析一行,释放内存。理论上可以解析任意大小的XML文件。
  • 缺点:使用过的元素不能再访问了,不能修改元素,只能查找。

DOM解析原理

目标

学习DOM解析的原理

DOM的概念

Document Object Model 文档对象模型

DOM解析原理

DOM 将整个XML文档加载到内存,生成一个DOM树,并获得一个Document对象,通过Document对象就可以对DOM进行操作。以下面books.xml文档为例。

[外链图片转存失败(img-SlAsErVh-1564584747367)(/1552305143011.png)]

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>

生成的DOM树

[外链图片转存失败(img-cJMuSk5W-1564584747370)(/1552305350183.png)]

DOM解析优缺点

优点:将整个XML文件加载到内存中,生成一棵DOM树。随意访问树上任何一个节点,可以修改和删除节点,程序开发比较方便。

缺点:占内存,如果XML文件很大,可能出现内存溢出。

Java中DOM解析开发包

[外链图片转存失败(img-wBthZSsM-1564584747371)(/1552305195234.png)]

​ 由于DOM方式解析XML文档所有都是节点Node,所有节点又都被封装到Document对象中,所以解析的重点就是获取Document对象。

小结

有哪两种XML的解析方式
SAX解析
DOM解析

DOM的解析原理:
将XML的所有内容读取到内存中,形成一颗DOM树

dom4j: 获取Document对象和根元素

目标

  1. 如何得到Document对象
  2. 如何通过Document得到根元素

导入dom4j的步骤

  1. 去官网下载 zip 包。http://www.dom4j.org/
    [外链图片转存失败(img-zBjXFxnC-1564584747372)(/1552305595501.png)]

  2. 在项目中创建一个文件夹:lib

  3. 将dom4j-2.1.1.jar文件复制到 lib 文件夹

  4. 在jar文件上点右键,选择 Add as Library -> 点击OK

  5. 在类中导包使用

得到Document对象

步骤

文件Contact.xml放在src目录下

  1. 创建一个SAXReader对象,用于读取 xml 文件
  2. 从类路径下加载xml文件,得到输入流对象
  3. 通过 SAXReader对象的read(InputStream in )方法,从输入流中读取,生成文档对象

代码

package com.itheima;

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

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;

/**
 1. 得到文档对象
 2. 得到根元素
 */
public class Demo3Document {

    public static void main(String[] args) throws FileNotFoundException, DocumentException {
        //1. 创建类: 读取XML文件
        SAXReader reader = new SAXReader();
        //不建议这么写
        //FileInputStream in = new FileInputStream("D:\\IdeaWork\\JavaEE105\\day23-xml\\src\\Contacts.xml");
        //src目录就是编译以后的类路径,从类路径下得到输入。
        InputStream in = Demo3Document.class.getResourceAsStream("/Contacts.xml");
        //2.通过reader来读取xml, 生成了一个document对象
        Document document = reader.read(in);
        //3. 输出文档
        System.out.println(document);
        //4. 得到文档以后,通过文档得到根元素
        Element rootElement = document.getRootElement();
        System.out.println(rootElement);
    }

}

Document常用方法

[外链图片转存失败(img-9QYdCVvi-1564584747373)(/1552305787000.png)]

小结

  1. 如何得到Document对象
    Document document = 解析器.read(输入流);

    // 1.创建了一个DOM解析器
    SAXReader reader = new SAXReader();
    InputStream in = Demo01.class.getResourceAsStream("/Contact.xml");// 直接就是获取src
    
    // 2.解析XML得到document对象
    Document document = reader.read(in);
    
  2. 调用哪个方法得到根元素:

    Element rootElement = document.getRootElement();
    

dom4j: 元素对象Element

目标

能够使用元素对象的方法

什么是Element

就是元素对象,即标签

Element常用方法

方法名 功能说明
String getName() 得到元素名字
Element element(String name) 得到当前元素下指定名字的子元素,如果有很多名字相同的返回第一个
List elements() 得到当前元素下所有子元素
List elements(String name) 得到当前元素下指定名字的子元素返回集合

元素使用的案例

需求

元素方法的使用,得到第一个contact下所有的子元素,并且输出元素名

步骤

  1. 得到SAXReader对象
  2. 得到Document对象
  3. 得到根元素
  4. 得到contact元素
  5. 得到contact下所有的子元素,并输出子元素的名字

代码

package com.itheima;

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

import java.io.InputStream;
import java.util.List;

/**
 元素方法的使用
 */
public class Demo3Element {

    public static void main(String[] args) throws DocumentException {
        //1. 得到SAXReader对象
        SAXReader reader = new SAXReader();
        InputStream in = Demo3Element.class.getResourceAsStream("/Contacts.xml");
        //2. 得到Document对象
        Document document = reader.read(in);
        //3. 得到根元素
        Element rootElement = document.getRootElement();
        //4. 得到contact元素
        Element contact = rootElement.element("contact");
        //System.out.println(contact);
        //5. 得到contact下所有的子元素,并输出子元素的名字
        List<Element> elements = contact.elements();
        for (Element element : elements) {
            //只输出标签名
            System.out.println(element.getName());
        }
    }
}

小结

Element对象的方法

方法名 功能说明
String getName() 获取元素的名称
Element element(String name) 获取指定名称的子元素,有多个返回第一个
List elements() 获取所有的子元素
List elements(String name) 获取所有指定名称的子元素

dom4j: 属性对象Attribute

目标

能够得到元素中的属性并使用

什么是Attribute对象

<contact id="1" vip="true">

如:id=“1”

Element中与属性相关方法

得到属性的前提是:先得到元素

Element中的方法 功能说明
String attributeValue(String name) 通过属性名直接得到属性值
Attribute attribute(String name) 通过属性名得到属性对象
List attributes() 得到当前元素所有的属性对象

Attribute常用方法

[外链图片转存失败(img-gOSwTx0L-1564584747375)(/1552306372013.png)]

得到属性值的两种方式

  1. 先得到Attribute对象,再通过Attribute对象得到属性的值
  2. 通过方法attributeValue()直接得到属性值

属性的案例

需求

  1. 使用2种方式,得到contact上id属性值
  2. 在contact元素上添加一个vip的属性值为true/false,得到contact上所有的属性名和属性值

效果

[外链图片转存失败(img-wP8PQkNj-1564584747376)(/1552306491790.png)]

步骤

  1. 创建DOM解析器
  2. 调用read 方法,读取 xml 文件
  3. 得到根元素
  4. 获得第1个contact元素对象
  5. 通过方式1:得到contact上id属性值
  6. 通过方式2:得到contact上id属性值
  7. 得到contact上所有的属性名和属性值

代码

package com.itheima;

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

import java.util.List;

public class Demo4Attribute {

    public static void main(String[] args) throws DocumentException {
        //1. 创建SAXReader
        SAXReader reader = new SAXReader();
        //2. 调用read 方法,读取 xml 文件
        Document document = reader.read(Demo4Attribute.class.getResourceAsStream("/Contacts.xml"));
        //3. 得到根元素
        Element rootElement = document.getRootElement();
        //4. 获得第1个contact元素对象
        Element contact = rootElement.element("contact");
        //5. 通过方式1:得到contact上id属性值
        Attribute idAttr = contact.attribute("id");
        String idValue = idAttr.getValue();
        System.out.println(idValue);
        //6. 通过方式2:得到contact上id属性值
        String id = contact.attributeValue("id");
        System.out.println(id);
        //7. 得到contact上所有的属性名和属性值
        List<Attribute> attributes = contact.attributes();
        for (Attribute attribute : attributes) {
            System.out.println("属性名:" + attribute.getName());
            System.out.println("属性值:" + attribute.getValue());
        }
    }
}

小结

Element中的方法 功能说明
Attribute attribute(String name) 通过属性名获取属性对象
String attributeValue(String name) 通过属性名获取属性值
List attributes() 获取当前元素上的所有属性对象

dom4j: 获取文本内容

目标

通过元素对象得到文本字符串

文本内容

得到文本元素的前提:先得到元素对象

  • 注:空格、换行、制表符:也是属于文本的一部分,所以在解析xml文件的时候,格式化XML文件要注意。

元素中得到文本有关的方法

Element元素中的方法 说明
String getText() 得到元素中文本
String elementText(元素名) 得到子元素中文本
String elementTextTrim(元素名) 得到子元素中文本,去掉先后空格

案例:对文本的操作

需求

得到第1个contact中的name元素,输出name元素的文本。分别通过下面三个方法得到:

  1. 通过getText()方法得到
  2. 直接得到元素的内容
  3. 得到去掉空格的文本

步骤

  1. 解析XML得到Document对象
  2. 得到根元素
  3. 得到第一个contact标签
  4. 得到name标签中的文本
  5. 得到name标签
  6. 再得到name中的文本

代码

package com.itheima;

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

/**
 得到文本内容
 */
public class Demo5Text {

    public static void main(String[] args) throws DocumentException {
        //1. 创建SAXReader
        SAXReader reader = new SAXReader();
        //2. 调用read 方法,读取 xml 文件
        Document document = reader.read(Demo5Text.class.getResourceAsStream("/Contacts.xml"));
        //3. 得到根元素
        Element rootElement = document.getRootElement();
        //得到contact标签
        Element contact = rootElement.element("contact");
        //得到name标签中的文本
        Element name = contact.element("name");
        System.out.println(name.getText());
        //得到子元素的文本
        System.out.println(contact.elementText("name"));
        //得到子元素的文本并且去掉前后空格
        System.out.println(contact.elementTextTrim("name"));
    }

}

小结

Element元素中的方法 说明
String getText() 获取元素的文本
String elementText(子元素名) 获取指定的子元素的文本
String elementTextTrim(子元素名) 获取指定的子元素的文本,会去掉左右空格回车

案例:XML解析案例

目标

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

运行效果

[外链图片转存失败(img-Dy570mUa-1564584747378)(/1552307147703.png)]

数据准备

Contact.xml


<contactList>
    <contact id="1">
        <name>潘金莲name>
        <gender>gender>
        <email>[email protected]email>
    contact>
    <contact id="2">
        <name>武松name>
        <gender>gender>
        <email>[email protected]email>
    contact>
    <contact id="3">
        <name>武大狼name>
        <gender>gender>
        <email>[email protected]email>
    contact>
contactList>

Contact.java实体类

package com.itheima.entity;

/**
 * 联系人实体类
 */
public class Contact {
    private int id;
    private String name;
    private String gender;
    private String email;

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

    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;
    }
}

步骤

  1. 创建集合对象用于封装所有的联系人
  2. 获得所有的contact元素
  3. 遍历contact元素集合
  4. 每个contact创建一个联系人对象
  5. 得到contact下的子元素的文本封装其它的属性
  6. 将联系人对象添加到集合中
  7. 遍历输出每一个集合中联系人对象

代码

package com.itheima;

import com.itheima.entity.Contact;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.util.ArrayList;
import java.util.List;

public class Demo6Contact {

    public static void main(String[] args) throws DocumentException {
        //1. 得到SaxReader
        SAXReader reader = new SAXReader();
        //2. 得到文档对象
        Document document = reader.read(Demo6Contact.class.getResourceAsStream("/Contact.xml"));
        //3. 得到根元素
        Element rootElement = document.getRootElement();
        //4. 创建集合
        List<Contact> list = new ArrayList<>();
        //5. 得到所有联系人
        List<Element> contactElements = rootElement.elements();
        //每个就是一个联系人
        for (Element contactElement : contactElements) {
            //创建一个联系人
            Contact contact = new Contact();
            //System.out.println(contactElement.getName());  //打印标签名
            //得到id属性值,将字符串转成int类型
            int id = Integer.parseInt(contactElement.attributeValue("id"));
            contact.setId(id);
            //得到子元素中文本
            contact.setName(contactElement.elementText("name"));
            contact.setGender(contactElement.elementText("gender"));
            contact.setEmail(contactElement.elementText("email"));
            //将当前对象添加到集合中
            list.add(contact);
        }
        //打印集合中所有的联系人
        for (Contact contact : list) {
            System.out.println(contact);
        }
    }

}

小结

案例中使用到的方法 作用
List elements(子元素名) 获取所有指定名称的子元素
String attributeValue(属性名) 通过属性名得到属性值
String elementText(子元素名) 得到指定名称的子元素的文本内容

dom4j中与XPath表达式有关的方法

目标

  1. 学习XPath的概念
  2. 学习Dom4j与XPath相关的方法

什么是XPath

作用:在XML中通过路径表达式可以很方便的得到我们需要的内容,让XML解析更加简单

XPath表达式分类

  1. 绝对路径
  2. 相对路径
  3. 全文搜索
  4. 属性查找

什么是Node对象

DOM树中的每个节点就是Node

[外链图片转存失败(img-Ozh0uW0j-1564584747380)(/1552308501088.png)]

dom4j中与XPath相关的方法

注:使用XPath需要另外导入 jaxen-1.1.2.jar包[外链图片转存失败(img-Sbpbzd9h-1564584747381)(/1557216821239.png)]

Node对象的方法 功能说明
Node selectSingleNode(String xpath) 通过xpath得到一个节点
List selectNodes(String xpath) 通过xpath得到一组节点

小结

Node对象的方法 功能说明
Node selectSingleNode(String xpath) 通过XPath表达式得到一个节点
List selectNodes(String xpath) 通过XPath表达式得到多个节点

XPath:绝对路径和相对路径

目标

  1. 学习XPath绝对路径的使用
  2. 学习XPath相对路径的使用

绝对路径语法

[外链图片转存失败(img-Sg4EfxDo-1564584747383)(/1552308629483.png)]

绝对路径示例

需求

采用绝对路径获取从根节点开始逐层的查找/contactList/contact/name 节点列表并打印信息

步骤

  1. 创建 XML 解析器,读取 XML 文档并获得Document对象
  2. 定义 Xpath 表达式:/contactList/contact/name
  3. 调用Document对象的selectNodes()方法执行Xpath获得节点集合
  4. 遍历输出每个节点

代码

package com.itheima;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;
import org.junit.Before;
import org.junit.Test;

import java.util.List;

/**
 使用xpath
 */
public class Demo7Xpath {

    private Document document;

    //在每个测试方法之前执行的方法
    @Before
    public void init() throws DocumentException {
        //1. 得到SaxReader
        SAXReader reader = new SAXReader();
        //2. 得到文档对象
        document = reader.read(Demo7Xpath.class.getResourceAsStream("/Contact.xml"));
    }
    /**
     使用绝对路径
     */
    @Test
    public void testAbsolute() {
        String xpath = "/contactList/contact/name";
        //得到所有name元素
        List<Node> nodeList = document.selectNodes(xpath);
        for (Node node : nodeList) {
            System.out.println(node.getText());
        }
    }
}

相对路径的语法

[外链图片转存失败(img-MYcIhYz2-1564584747384)(/1552308854372.png)]

相对路径的示例

需求

  1. 先采用绝对路径获取 contactList 节点
  2. 再采用相对路径获取下一级contact 节点的name子节点并打印信息。

步骤

  1. 定义 Xpath 表达式:/contactList
  2. 调用Document对象的 selectSingleNode 方法执行Xpath获得根节点对象
  3. 通过根节点对象调用selectNodes方法执行相对路径表达式:./contact/name
  4. 打印输出所有的节点

代码

/**
 使用相对路径
 */
@Test
public void testRelative() {
    //通过绝对路径得到/contactList
    Node node = document.selectSingleNode("/contactList");
    //通过相对路径得到name
    Node nameNode = node.selectSingleNode("./contact/name");
    System.out.println(nameNode.getText());
}

小结

  1. 什么是XPath的绝对路径?

    /根元素/子元素/孙元素/...  不能越级
    /开头的就是绝对路径
    
  2. 什么是XPath的相对路径?

    ./子元素/孙元素/	不能越级
    ./相对路径
    

XPath:全文搜索和属性查找

目标

  1. 学习XPath全文搜索的使用
  2. 学习XPath属性查找的使用

全文搜索语法

[外链图片转存失败(img-ORVmDydV-1564584747386)(/1552310075137.png)]

举例

举例 说明
//contact 找contact元素,无论元素在哪里
//contact/name 找contact,无论在哪一级,但name一定是contact的子节点
//contact//name contact无论在哪一种,name只要是contact的子孙元素都可以找到

全文搜索示例

需求

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

步骤

  1. 创建Xpath表达式 //name
  2. 使用selectNodes()方法查询所有的name节点

代码

/**
 全文搜索
 */
@Test
public void testGlobalSearch() {
    List<Node> nodes = document.selectNodes("//name");
    for (Node node : nodes) {
        System.out.println(node.getText());
    }
}

属性查找语法

[外链图片转存失败(img-5xHRoL4d-1564584747387)(/1552310301097.png)]

属性查找的示例

  1. 查找所有id属性节点
  2. 查找包括id属性的contact元素
  3. 查找包括id属性且属性名为的contact元素

步骤

  1. 创建Xpath表达式
  2. 使用selectNodes()方法查询所有的节点

代码

/**
 属性查找
 */
@Test
public void testAttributeFind() {
    //1. 查找所有id属性节点
    /*List nodes = document.selectNodes("//@id");
    //是属性对象Attribute
    for (Node node : nodes) {
        //输出属性值
        Attribute a = (Attribute) node;
        System.out.println("属性值:" + a.getValue());
    }*/
    //2. 查找包括id属性的contact元素
    /*List nodeList = document.selectNodes("//contact[@id]");
    for (Node node : nodeList) {
        System.out.println(node.getName());
    }*/
    //3. 查找包括id属性且属性名为的contact元素
    Node node = document.selectSingleNode("//contact[@id=2]");
    System.out.println(node.getName());
}

小结

XPath表达式分类 语法
绝对路径 /根元素/子元素/孙元素 以/开头就是绝对路径
相对路径 ./子元素/孙元素 以./开头的就是相对路径
全文路径 //元素名 以//开头就是全文搜索
属性查找 //@属性 找到的是属性

//元素名[@属性名] 找到包含指定属性名的元素

//元素名[@属性名=‘值’] 找到包含指定属性名并且属性值相等的元素

学习总结

  1. 能够说出 XML 的作用

    1. 数据交换
    2. 配置文件
  2. 了解 XML 的组成元素

    1. 文档声明
    2. 元素/标签
    3. 属性
    4. 注释
    5. 实体字符
    6. CDATA字符数据区
    7. 处理指令
  3. 能够说出有哪些 XML约束技术

    1. DTD(弱)
    2. Schema(强)
      1. 支持数据类型
      2. 本身xsd也是一个XML文件,不容易写错
      3. 一个XML可以有多个xsd约束文件
  4. 能够说出解析 XML 文档 DOM方式原理
    DOM解析会读取整个XML,将所有的内容在内存中建立一颗DOM树

    [外链图片转存失败(img-SSekPVEk-1564584747388)(/1552305350183.png)]

  5. 能够说出Dom4j常用的类

    组成 说明
    Document 文档对象
    Node 节点
    Element 元素
    Attribute 属性
    Text 文本
  6. 能够通过Dom4j得到文档对象

    SAXReader reader = new SAXReader();
    Document document = reader.read(Demo05.class.getResourceAsStream("/Contact.xml"));
    
  7. 能够读取Dom树上的元素对象

    Document方法名 功能说明
    Element getRootElement() 得到根元素
    Element方法名 功能说明
    String getName() 得到元素的标签名
    Element element(String name) 通过元素名字得到元素对象
    List elements() 得到所有的子元素
    List elements(String name) 得到指定名字的所有子元素
  8. 能够使用 XPath 解析 XML 文档

    Document对象的方法 功能说明
    Node selectSingleNode(String xpath) 得到一个节点
    List selectNodes(String xpath) 得到多个节点
XPath表达式分类 语法
绝对路径 /根元素/子元素/孙元素 以/开头就是绝对路径
相对路径 ./子元素/孙元素 以./开头的就是相对路径
全文路径 //元素名 以//开头就是全文搜索
属性查找 //@属性 找到的是属性
//元素名[@属性名] 找到包含指定属性名的元素
//元素名[@属性名=‘值’] 找到包含指定属性名并且属性值相等的元素

xpath: 爬虫 去别人的网页上搜索你想要的数据

你可能感兴趣的:(12----xml文件+xml文件的解析(dom4j包))