Dom4j的基本使用 , XML解析方式和解析器 ,Dom4J结合XPath解析XML

news2024/11/13 12:04:10

第二章 Dom4j

1 XML解析

1.1 解析概述

​ 当将数据存储在XML后,我们就希望通过程序获取XML的内容。我们使用Java基础所学的IO知识是可以完成的,不过需要非常繁琐的操作才可以完成,且开发中会遇到不同问题(只读、读写)。

人们为不同问题提供不同的解析方式,使用不同的解析器进行解析,方便开发人员操作XML。

1.2 解析方式和解析器

开发中比较常见的解析方式有三种,如下:

  1. DOM:要求解析器把整个XML文档装载到内存,并解析成一个Document对象

    a)优点:元素与元素之间保留结构关系,故可以进行增删改查操作。

    b)缺点:XML文档过大,可能出现内存溢出

  2. SAX:是一种速度更快,更有效的方法。它逐行扫描文档,一边扫描一边解析。并以事件驱动的方式进行具体解析,每执行一行,都触发对应的事件。

    a)优点:处理速度快,可以处理大文件

    b)缺点:只能读,逐行后将释放资源,解析操作繁琐。

  3. PULL:Android内置的XML解析方式,类似SAX。(了解)

解析器,就是根据不同的解析方式提供具体实现。有的解析器操作过于繁琐,为了方便开发人员,有提供易于操作的解析开发包

在这里插入图片描述

常见的解析器

在这里插入图片描述

小结

xml的常用解析方式:

  1. DOM
  2. SAX
  3. PULL

基于解析方式,常用的解析工具包: Dom4j

2 Dom4j的基本使用

2.1 DOM解析原理及结构模型

解析原理

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

<?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>

结构模型

DOM中的核心概念就是节点,在XML文档中的元素、属性、文本,在DOM中都是节点!所有的节点都封装到了Document对象中。

在这里插入图片描述

结论:使用Document对象,就可以去访问DOM树中的每一个节点

引入dom4j的jar包

去官网下载 zip 包。http://www.dom4j.org/
在这里插入图片描述

通常我们会在项目中创建lib文件夹,将需要依赖的库放在这里。

库导入方式:

  1. 在IDEA中,选择项目鼠标右键—>弹出菜单–>open Module settings”–>Dependencies–>±->JARs or directories… 找到dom4j-1.6.1.jar,成功添加之后点击"OK" 即可。

  2. 直接右键选择:Add as Library

    在这里插入图片描述

小结

dom4j的解析思想,先把xml文档加载到内存中,从而得到一个DOM树,并创建一个Document对象去维护dom树。

利用Document对象,就可以去解析DOM树(解析XML文件)

2.2 常用的方法

dom4j 必须使用核心类SaxReader加载xml文档获得Document,通过Document对象获得文档的根元素,然后就可以操作了。

SAXReader对象
方法作用
SAXReader sr = new SAXReader();构造器
Document read(String url)加载执行xml文档
Document对象
方法作用
Element getRootElement()获得根元素
Element对象
方法作用
List<Element> elements(String ele )获得指定名称的所有子元素。可以不指定名称
Element element(String ele)获得指定名称第一个子元素。
String getName()获得当前元素的元素名
String attributeValue(String attrName)获得指定属性名的属性值
String elementText(Sting ele)获得指定名称子元素的文本值
String getText()获得当前元素的文本内容

小结

解析xml的步骤:

  1. 创建SaxReader对象,调用read方法关联xml文件,得到一个Document对象
  2. 通过Document对象,获取根元素
  3. 获取根元素之后,就可以层层深剥,运用Element相关的API进行解析其子元素
2.3 方法演示

复制资料下的常用xml中"books.xml",内容如下:

<?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>

注意:为了便于解析,此xml中没有添加约束

解析此文件,获取每本书的id值,以及书本名称,作者名称和价格.

步骤分析:

  1. 创建一个SaxReader对象,调用read方法加载一个xml文件获得文档对象
  2. 通过文档对象,获取根元素
  3. 通过根元素一层一层的进行解析子元素。
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.util.List;

public class Demo01 {
    public static void main(String[] args) throws DocumentException {
        //1. 创建一个SaxReader对象,调用read方法加载一个xml文件获得文档对象
        SAXReader sr = new SAXReader();
        Document doc = sr.read("day15/xml/book.xml");

        //2. 通过文档对象,获取根元素
        Element rootElement = doc.getRootElement();

        //3. 通过根元素一层一层的进行解析子元素。
        //获取所有的子元素
        List<Element> bookElements = rootElement.elements("book");

        for (Element bookElement : bookElements) {
            //System.out.println(bookElement);
            //解析属性
            String id = bookElement.attributeValue("id");
            System.out.println("id = " + id);
            //获取子元素文本
            String name = bookElement.elementText("name");
            String author = bookElement.elementText("author");
            String sale = bookElement.elementText("sale");
            System.out.println("name = " + name);
            System.out.println("author = " + author);
            System.out.println("sale = " + sale);



            System.out.println("----------------------");
        }
        
    }
}

需求二:

将xml中文件数据解析成为java对象,每个book解析为一个book类型的对象。然后将book对象放到一个集合中存储。

<?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>

步骤分析:

  1. 先创建一个Book类对应book元素
  2. 创建一个ArrayList集合用来存储解析后的book对象
  3. 创建SaxReader对象,调用read方法加载xml文件,得到文档对象
  4. 通过文档对象获取根元素,然后层层解析

代码实现:

public class Demo02 {
    public static void main(String[] args) throws DocumentException {
        //定义一个集合用来存储解析的Book对象
        ArrayList<Book> books = new ArrayList<>();



        //1. 创建一个SaxReader对象,调用read方法加载一个xml文件获得文档对象
        SAXReader sr = new SAXReader();
        Document doc = sr.read("day15/xml/book.xml");

        //2. 通过文档对象,获取根元素
        Element rootElement = doc.getRootElement();

        //3. 通过根元素一层一层的进行解析子元素。
        //获取所有的子元素
        List<Element> bookElements = rootElement.elements("book");

        for (Element bookElement : bookElements) {
            //System.out.println(bookElement);
            //解析属性
            String id = bookElement.attributeValue("id");
            System.out.println("id = " + id);
            //获取子元素文本
            String name = bookElement.elementText("name");
            String author = bookElement.elementText("author");
            String sale = bookElement.elementText("sale");

            //将解析的字符串封装成为对象,放到集合
            Book book = new Book(id,name,author,sale);
            books.add(book);

        }


        //将集合遍历,打印book对象
        for (Book book : books) {
            System.out.println("book = " + book);
        }

    }
}

class Book{
    private String id;
    private String name;
    private String author;
    private String sale;

    public Book() {
    }

    public Book(String id, String name, String author, String sale) {
        this.id = id;
        this.name = name;
        this.author = author;
        this.sale = sale;
    }

    public String getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

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

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    public String getSale() {
        return sale;
    }

    public void setSale(String sale) {
        this.sale = sale;
    }

    @Override
    public String toString() {
        return "Book{" +
                "id='" + id + '\'' +
                ", name='" + name + '\'' +
                ", author='" + author + '\'' +
                ", sale='" + sale + '\'' +
                '}';
    }
}

3 Dom4J结合XPath解析XML(了解)

3.1 介绍

XPath使用路径表达式来选取XML/HTML 文档中的元素节点或属性节点。节点是通过沿着路径 (path) 来选取的。XPath在解析XML/HTML文档方面提供了一独树一帜的路径思想。

3.2 XPath使用步骤

步骤1:导入jar包(dom4j和jaxen-1.1-beta-6.jar)

步骤2:通过dom4j的SaxReader获取Document对象

步骤3: 利用Xpath提供的api,结合xpath的语法完成选取XML文档元素节点进行解析操作。

Node接口中存在以下方法:

方法作用
List<Element> selectNodes("路径表达式")获取符合表达式的元素集合
Element selectSingleNode("路径表达式")获取符合表达式的唯一元素

我们熟知的Document,Element等都是Node的子类型,因此也能使用上述selectNode的方法。如下图

在这里插入图片描述

3.3 XPath语法(了解)

XPath也是一种解析XML或者HTML的方式。

  • XPath表达式,就是用于选取XML文档中节点的表达式字符串。获取XML文档节点元素一共有如下4种XPath语法方式:
    1. 绝对路径表达式方式 例如: /元素/子元素/子子元素…
    2. 相对路径表达式方式 例如: 子元素/子子元素… 或者 ./子元素/子子元素…
    3. 全文搜索路径表达式方式 例如: //子元素//子子元素
    4. 谓语(条件筛选)方式 例如: //元素[@attr]

在xml解析得到的一个文档对象中,Document,Element,Attribute,Text ,都是接口Node的子类型。

Node中存在两个方法,可以结合xpath使用查询节点:

List<Node>  selecteNodes(路径) :将所有满足路径的节点给获取出来
Node  selecteSingleNode(路径) :获取单个满足路径的节点

xpath使用步骤:

  1. 创建SAXReader对象,调用read方法,关联xml文件。得到Document对象
  2. 就可以使用Document对象来调用方法传入xpath路径
3.3.1 绝对路径表达式(了解)

格式:

String xpath="/根元素/子元素/子子元素...";

绝对路径是以“/”开头,一级一级描述标签的层级路径就是绝对路径,这里注意不可以跨层级

  • 演示需求(将素材中的Contact.xml拷贝到项目中)

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

实现步骤:

  1. 先创建SAXReader对象,调用read方法,将Contact.xml关联,得到Document对象

  2. 定义绝对路径

  3. 调用selectedNodes

public class Demo01 {
    public static void main(String[] args) throws DocumentException {
        //采用绝对路径获取从根节点开始逐层的查找name节点列表并打印信息

        //1. 先创建SAXReader对象,调用read方法,将Contact.xml关联,得到Document对象
        SAXReader sr = new SAXReader();
        Document doc = sr.read("day15/xml/Contact.xml");
        //2. 定义绝对路径
        String xpath = "/contactList/contact/name";
        //3. 调用selectedNodes
        List<Node> nameNodes = doc.selectNodes(xpath);

        for (Node nameNode : nameNodes) {
            String text = nameNode.getText();
            System.out.println("text = " + text);
        }
        
    }
}

text = 潘金莲
text = 武松
text = 武大狼
3.2 相对路径表达式(了解)
  • 相对路径介绍

    格式:

    String xpath2="./子元素/子子元素";		// "./"代表当前元素路径位置
    
  • 需求:
    先采用绝对路径获取 contact 节点 再采用相对路径获取下一级name子节点并打印信息。

public class Demo01 {
    public static void main(String[] args) throws DocumentException {
        //先采用绝对路径获取 contact  节点 再采用相对路径获取下一级name子节点并打印信息。
        //1. 先创建SAXReader对象,调用read方法,将Contact.xml关联,得到Document对象
        SAXReader sr = new SAXReader();
        Document doc = sr.read("day15/xml/Contact.xml");

        //先使用绝对路径,获取contact
        List<Node> contactNodes = doc.selectNodes("/contactList/contact");
        for (Node contactNode : contactNodes) {
            //使用相对路径获取name,并获取文本打印

            Node node = contactNode.selectSingleNode("./name");
            System.out.println("node.getText() = " + node.getText());

        }

    }
}


node.getText() = 潘金莲
node.getText() = 武松
node.getText() = 武大狼
3.3 全文搜索路径表达式(了解)
  • 全文搜索路径介绍

    格式:

    String xpath1="//子元素//子子元素";
    

    “/”符号,代表逐级写路径

    “//”符号,不用逐级写路径,可以直接选取到对应的节点,是全文搜索匹配的不需要按照逐层级

    举例说明
    //contact找contact元素,无论元素在哪里
    //contact/name找contact,无论在哪一级,但name一定是contact的子节点
    //contact//namecontact无论在哪一种,name只要是contact的子孙元素都可以找到
    //name
  • 需求:直接全文搜索所有的 name元素并打印

    public class Demo01 {
        public static void main(String[] args) throws DocumentException {
            //需求:直接全文搜索所有的 name元素并打印
            //1. 先创建SAXReader对象,调用read方法,将Contact.xml关联,得到Document对象
            SAXReader sr = new SAXReader();
            Document doc = sr.read("day15/xml/Contact.xml");
    
            List<Node> nodes = doc.selectNodes("//name");
            for (Node node : nodes) {
                System.out.println("node.getText() = " + node.getText());
            }
    
        }
    }
    
    

结论:

  • / 表示根节点 (不能跨层级)
    
  • // 表示全文任意节点 (可以跨层级)
    
3.4 谓语(条件筛选 了解)
  • 介绍

    谓语,又称为条件筛选方式,就是根据条件过滤判断进行选取节点

    格式:

    String xpath1="//元素[@属性名]";//查找元素对象,全文中只要含有该属性名的元素
    String xpath2="//元素[@属性名=value]";//查找元素对象,全文中只要含有该属性,并指定的值
    
  • 需求:查找含有id属性的contact元素

    public class Demo01 {
        public static void main(String[] args) throws DocumentException {
            //查找含有id属性的contact元素
            SAXReader sr = new SAXReader();
            Document doc = sr.read("day15/xml/Contact.xml");
    
            //List<Node> nodes = doc.selectNodes("//contact[@id]");//获取含有属性id的元素
            List<Node> nodes = doc.selectNodes("//contact[@id=1]");//获取含有属性并且值为1的元素
            for (Node node : nodes) {
                //将节点,先转换Element
                Element contact = (Element) node;
                System.out.println("contact.elementText(\"name\") = " + contact.elementText("name"));
            }
    
        }
    }
    

小结

  • 在xpath解析xml方式中,最核心的就是使用了"路径表达式"

    • xpath是利用"路径表达式"实现对xml文件的解析
  • 路径表达式的语法:

    1. 绝对路径表达式

      /根元素/子元素/子子元素/....   (一层一层查找)
      
    2. 相对路径表达式

      ./子元素/子子元素/.....
      
    3. 全文搜索路径表达式

      //元素     (会跨层级进行全文查找)
      
    4. 条件筛选表达式

      //元素[@属性名]
      //元素[@属性名=属性值]
      

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1872655.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

社交App广告优化新篇章:Xinstall引领用户体验升级,助力买量效果提升

随着移动互联网的快速发展&#xff0c;社交App已经成为人们生活中不可或缺的一部分。然而&#xff0c;在竞争激烈的市场环境下&#xff0c;如何有效地进行广告投放&#xff0c;吸引并留住用户&#xff0c;成为了每个社交App运营者面临的重大挑战。今天&#xff0c;我们就来谈谈…

乐观锁和悲观锁(MySQL和Java)

乐观锁和悲观锁(MySQL和Java) 在并发编程中&#xff0c;为了确保数据的一致性和完整性&#xff0c;我们通常需要使用锁机制来控制对共享资源的访问。锁主要分为两种&#xff1a;乐观锁和悲观锁。本文将详细介绍这两种锁的概念、工作原理以及它们的优缺点。 悲观锁 悲观锁(Pe…

字节码编程ASM之插桩方法执行耗时

写在前面 源码 。 本文看下如何对已有类进行插装。以最经典的方法执行耗时作为例子。 1&#xff1a;编码 假定有如下的代码&#xff1a; public class MyMethod {public String queryUserInfo(String uid) {System.out.println("xxxx");System.out.println("…

visual studio2022配置和使用protobuf

上图证明&#xff0c;我真的测了好多遍&#xff0c;测了好多版本的protobuf&#xff0c;花了很多时间。不过好在最后在vs2022上测通了。 下载protobuf 这里是protobuf下载的地址。 Releases protocolbuffers/protobuf GitHub 个人使用的3.21.9这个版本才跑通的。 1、首先…

【递归、搜索与回溯】floodfill算法二

floodfill算法二 1.被围绕的区域2.太平洋大西洋水流问题3.扫雷游戏4.衣橱整理 点赞&#x1f44d;&#x1f44d;收藏&#x1f31f;&#x1f31f;关注&#x1f496;&#x1f496; 你的支持是对我最大的鼓励&#xff0c;我们一起努力吧!&#x1f603;&#x1f603; 1.被围绕的区域…

【OpenSSH】关于操作系统中的自带的SSH你知道怎么用吗

希望文章能给到你启发和灵感&#xff5e; 如果觉得文章对你有帮助的话&#xff0c;点赞 关注 收藏 支持一下博主吧&#xff5e; 阅读指南 开篇说明一、基础环境说明1.1 硬件环境1.2 软件环境 二、如何开启SSH服务2.1 什么是OpenSSH2.2 对于Windows 10, Windows 11系统2.2.1 如…

bug记录-XFTP传输中文文件夹乱码

bug记录-XFTP传输中文文件夹乱码 今日想往服务器中同步一些脚本,脚本文件夹是中文命名的,用XFTP导入后发现文件夹名称是乱码的 但是在XFTP上显示是正常的 这是因为window默认是GBK编码 linux是UTF-8编码 所以我们只需要把XFTP会话的编码改为UTF-8就可以了 首先点击文件-当前…

【Android面试八股文】Framework面试:Handler怎么进行线程通信的?原理是什么?

文章目录 Handler整体思想Handler工作流程Handler工作流程图总结Handler整体思想 在多线程的应用场景中,将工作线程中需更新 UI 的操作信息 传递到 UI 主线程,从而实现 工作线程对 UI 的更新处理,最终实现异步消息的处理。 Handler工作流程 Handler 机制的工作流程主要包括…

VUE中,table border属性的不同使用方式

在vue中&#xff0c;使用table&#xff0c;在给table设置边框属性时&#xff0c;按照以往的习惯&#xff1a; <table border"1px solid"><table> 这种写法&#xff0c;产生的效果如下&#xff1a;下边、右边的边框明显和上边、左边不同。border属性设置…

【多维动态规划】Leetcode 97. 交错字符串【中等】

交错字符串 给定三个字符串 s1、s2、s3&#xff0c;请你帮忙验证 s3 是否是由 s1 和 s2 交错 组成的。 两个字符串 s 和 t 交错 的定义与过程如下&#xff0c;其中每个字符串都会被分割成若干 非空 子字符串 子字符串 是字符串中连续的 非空 字符序列。 s s1 s2 … snt…

2024年5月90篇代码大模型论文最全整理

引言&#xff1a; 本文整理 2024 年 5 月发布的 90 篇代码大模型相关论文&#xff0c;其中包括 17 篇发表在今年 ICLR 的论文。根据论文内容&#xff0c;我们将这些论文整理为了基座模型、代码微调、测试基准、代码 Agent、低资源语言处理、AI 代码安全与分析、人机交互、软件…

Lean4Game 开发教程 | 数学形式化

引言 Lean 是一门用于形式化证明的编程语言&#xff0c;它允许严格证明数学定理和验证软件代码的正确性。 本篇介绍 Lean 游戏的编写和发布方式。这类游戏不仅利于对 Lean 本身的学习&#xff0c;对学科知识的理解&#xff0c;还能推动数学圈内人对 Lean 的接触学习。 Lean4…

你不知道的物联网产品有那么多

目录 1. 智能农业设备 ​编辑1.1 土壤感应器 1.2 自动喷灌系统 2. 智能医疗设备 ​编辑2.1 可穿戴健康监测设备 2.2 智能药盒 3. 智能城市基础设施 ​编辑3.1 智能垃圾桶 3.2 智能路灯 4. 智能物流与供应链 ​编辑4.1 货物跟踪设备 4.2 智能仓储系统 5. 智能网关 …

linux server下人脸检测与识别服务程序的系统架构设计

一、绪论 1.1 定义 1.2 研究背景及意义 1.3 相关技术综述 二、人脸检测与识别技术概述 2.1 人脸检测原理与算法 2.2 人脸识别技术及方法 2.3 人脸识别过程简介 三、人脸检测与识别服务程序的系统架构 3.1 系统架构设计 3.2 技术实现流程 四、后续设计及经验瞎谈 4.…

【Mac】Listen 1 for Mac(最强的音乐搜索工具)软件介绍

软件介绍 Listen 1 for Mac 是一款非常方便的音乐播放软件&#xff0c;主要功能是集成多个音乐平台&#xff0c;让用户可以方便地搜索、播放和管理音乐。它是一个用 Python 语言开发的免费开源综合音乐搜索工具项目&#xff0c;最大的亮点在于可以搜索和播放来自网易云音乐&am…

全国公共汽车、出租车拥有情况及客运量、货运量数据

基本信息. 数据名称: 全国公共汽车、出租车拥有情况及客运量、货运量数据 数据格式: Shp、Excel 数据时间: 2020-2022年 数据几何类型: 面 数据坐标系: WGS84 数据来源&#xff1a;中国城市统计年鉴 数据可视化. 2022年全年公共汽车客运总量数据示意图 2022年公路客…

Apifox 更新|定时任务、内网自部署服务器运行接口定时导入、数据库 SSH 隧道连接

Apifox 新版本上线啦&#xff01; 看看本次版本更新主要涵盖的重点内容&#xff0c;有没有你所关注的功能特性&#xff1a; 自动化测试支持设置「定时任务」支持内网自部署服务器运行「定时导入」数据库均支持通过 SSH 隧道连接自动化测试数据库操作优化 1、自动化测试支持设…

计算机语言vs指令vs中央处理器cpu

计算机中如何表示数据 在计算机中&#xff0c;所有数据和指令都是用二进制表示的&#xff0c;即0和1。这些0和1实际上是电压信号的高低电平&#xff0c;0通常表示低电平&#xff08;如0伏特&#xff09;&#xff0c;1表示高电平&#xff08;如5伏特&#xff09;。 指令系统&a…

基本的 Spring Boot 配置步骤和常见的配置项【创建,配置,日志,数据库,安全,MVC】

基本的 Spring Boot 配置步骤和常见的配置项【创建&#xff0c;配置&#xff0c;日志&#xff0c;数据库&#xff0c;安全&#xff0c;MVC】 学习总结 1、掌握 JAVA入门到进阶知识(持续写作中……&#xff09; 2、学会Oracle数据库入门到入土用法(创作中……&#xff09; 3、…

UE5基本操作(二)

文章目录 前言相机的移动速度修改默认地图使用初学者内容包文件夹结构 总结 前言 在我们的上一篇文章中&#xff0c;我们已经介绍了一些Unreal Engine 5&#xff08;UE5&#xff09;的基本操作。UE5是一款强大的游戏开发引擎&#xff0c;它提供了许多工具和功能&#xff0c;使…