XML 的解析技术 Dom4j


Dom4j

1. XML 的解析

  • 当将数据存储在 XML 后,我们就希望通过程序获取 XML 的内容,如果使用基础的 IO 知识是可以完成的,不过要非常繁琐的操作才可以完成,且开发中会遇到不同问题(只读、读写)。人们为不同问题提供不同的解析方式,使用不同的解析器进行解析,方便开发人员操作 XML。

2. 解析方式和解析器

  • 开发中比较常见的解析方式有三种,如下:
  1. DOM:要求解析器把整个 XML 文档装载到内存,并解析成一个 Document 对象;
    (a)优点:元素与元素之间保留结构关系,故可以进行增删改查操作;
    (b)缺点:XML 文档过大,可能出现内存溢出。
  2. SAX:是一种速度更快,更有效的方法。它逐行扫描文档,一边扫描一边解析。并以事件驱动的方式进行具体解析,每执行一行,都触发对应的事件;
    (a)优点:处理速度快,可以处理大文件;
    (b)缺点:只能读,逐行后将释放资源,解析操作繁琐。
  3. PULL:Android 内置的 XML 解析方式,类似 SAX;
  • 解析器,就是根据不同的解析方式提供具体实现。有的解析器操作过于繁琐,为了方便开发人员,有提供易于操作的解析开发包。
    在这里插入图片描述
  • 常见的解析开发包:
    • JAXP:sun 公司提供支持 DOM 和 SAX 开发包;
    • Dom4j:比较简单的的解析开发包(常用);
    • JDom:与 Dom4j 类似;
    • Jsoup:功能强大 DOM 方式的 XML 解析开发包,尤其对 HTML 解析更加方便;

3. Dom4j 的基本使用

a. DOM 解析原理及结构模型

  • 解析原理:XML DOM 和 HTML DOM 一样,XML 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 对象中。
  • 引入 Dom4j 的 jar 包:需要引入 “jar/dom4j-1.6.1.jar” , 在 IDEA 中,选择项目鼠标右键 >> 弹出菜单 >> open Module settings” >> Dependencies ->> + >> JARs or directories… 找到 dom4j-1.6.1.jar,成功添加之后点击"OK" 即可.
  • Dom4j 必须使用核心类 SaxReader 加载 XML 文档获得Document,通过 Document 对象获得文档的根元素,然后就可以操作了。

b. 常用的方法

i. SAXReader 对象

方法 作用
new SAXReader() 构造器
Document read(String url) 加载执行 xml 文档

ii. Document 对象

方法 作用
Element getRootElement() 获得根元素

iii. Element 对象

方法 作用
List elements([String ele]) 获得指定名称的所有子元素,可以不指定名称
Element element([String ele]) 获得指定名称第一个子元素,可以不指定名称
String getName() 获得当前元素的元素名
String attributeValue(String attrName) 获得指定属性名的属性值
String elementText(Sting ele) 获得指定名称子元素的文本值
String getText() 获得当前元素的文本内容

c. 方法演示

  • 复制资料下的常用 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 值,以及书本名称,作者名称和价格;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

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

public class Test {
    public static void main(String[] args) throws DocumentException {
        //1.创建核心对象
        SAXReader reader = new SAXReader();
        //2.读取xml文件
        Document document = reader.read(new File("Practice1/books.xml"));//相对路径是相对于工程而言的,所以要指定模块
        //3.获取根标签
        Element rootElement = document.getRootElement();
        System.out.println("根标签是:"+rootElement.getName());
        //4.获取book标签
        List<Element> bookElements = rootElement.elements();
        //5.遍历集合
        for (Element bookElement : bookElements) {
            //6.获取标签名
            String bookElementName = bookElement.getName();
            System.out.println("子标签:"+bookElementName);
            //7.获取id属性值
            String idValue = bookElement.attributeValue("id");
            System.out.println("属性id:"+idValue);
            //8.继续获取子标签
            List<Element> elements = bookElement.elements();
            //9.遍历
            for (Element element : elements) {
                //10.获取标签名
                System.out.println(element.getName());
                //11.获取文本
                System.out.println(element.getText());
            }
        }
    }
}
/*
输出
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by org.dom4j.io.SAXContentHandler (file:/C:/Users/80626/idea-workspace/Practice1/lib/dom4j-1.6.jar) to method com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser$LocatorProxy.getEncoding()
WARNING: Please consider reporting this to the maintainers of org.dom4j.io.SAXContentHandler
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
根标签是:books
子标签:book
属性id:0001
name
JavaWeb开发教程
author
张孝祥
sale
100.00元
子标签:book
属性id:0002
name
三国演义
author
罗贯中
sale
100.00元
 */

出现的 warning 是 jar 包版本和 JDK 的兼容性问题。

4. Dom4J 结合 XPath 解析 XML

a. 介绍

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

b. XPath 使用步骤

  • 步骤 1:导入 jar 包(dom4j 和 jaxen-1.1-beta-6.jar 执行 “set as Library”);
  • 步骤 2:通过 dom4j 的 SaxReader 获取 Document 对象;
  • 步骤 3:利用 Xpath 提供的 API,结合 XPath 的语法完成选取 XML 文档元素节点进行解析操作。

c. Document 常用的 API

方法 作用
List selectNodes(“表达式”) 获取符合表达式的元素集合
Element selectSingleNode(“表达式”) 获取符合表达式的唯一元素

d. XPath 语法

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

i. 绝对路径表达式

  • 格式:
    String xpath = “/元素/子元素/子子元素…”;
  • 绝对路径是以 “/” 开头,一级一级描述标签的层级路径就是绝对路径,这里注意不可以跨层级
  • 绝对路径是从根元素开始写路径的,这里开头的 “/” 代表 HTML 文档根元素,所以在绝对路径中不可以写根元素路径;
  • 演示需求(解析 XML 文档为 “资料\常用 xml 文件\index.html”)

需求:采用绝对路径获取从根节点开始逐层的 html/body/div/ul/li 节点列表并打印信息。

ii. 相对路径表达式

  • 格式:
    String xpath1 = “子元素/子子元素…”;//获取相对当前路径元素里面的子元素的选取;
    String xpath2 = “./子元素/子子元素”;//"./"代表当前元素路径位置;
    String xpath3 = “/子元素/子子元素”;//功能与xpath1格式功能一样;
  • 相对路径就是相对当前节点元素位置继续查找节点,需要使用JXNode.sel(xpath)进行执行相对路径表达式。

iii. 全文搜索路径表达式

  • 格式:
    String xpath1 = “//子元素//子子元素”;
  • 1 个 “/” 符号,代表逐级写路径,而 2 个“//”符号,不用逐级写路径,可以直接选取到对应的节点,是全文搜索匹配的不需要按照逐层级。

iv. 谓语(条件筛选)

  • 谓语,又称为条件筛选方式,就是根据条件过滤判断进行选取节点;
  • 格式:
    String xpath1 = “//元素[@attr1=value]”;//获取元素属性attr1=value的元素;
    String xpath2 = “//元素[@attr1>value]/@attr1”//获取元素属性attr1>value的d的所有attr1的值;
    String xpath3 = “//元素[@attr1=value]/text()”;//获取符合条件元素体的自有文本数据;
    String xpath4 = “//元素[@attr1=value]/html()”;//获取符合条件元素体的自有html代码数据;
    String xpath3 = “//元素[@attr1=value]/allText()”;//获取符合条件元素体的所有文本数据(包含子元素里面的文本)。

e. 演示

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

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

public class Test {
    public static void main(String[] args) throws DocumentException {
        //1.创建核心对象
        SAXReader reader = new SAXReader();
        //2.读取xml文件
        Document document = reader.read(new File("Practice1/books.xml"));
        //3.使用Xpath
        //全文搜索路径表达式
        List<Element> list = document.selectNodes("//sale");
        for (Element element : list) {
            System.out.println(element.getText());
        }
        //谓语表达式
        Element ele = (Element) document.selectSingleNode("//book[@id='0001']/sale");
        System.out.println(ele.getText());
    }
}
/*
输出
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by org.dom4j.io.SAXContentHandler (file:/C:/Users/80626/idea-workspace/Practice1/lib/dom4j-1.6.jar) to method com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser$LocatorProxy.getEncoding()
WARNING: Please consider reporting this to the maintainers of org.dom4j.io.SAXContentHandler
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
100.00元
100.00元
100.00元
 */


发布了310 篇原创文章 · 获赞 315 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/Regino/article/details/105191875