Java中XML解析的方式介绍和实现

2023-12-23 09:37:51

在日常开发中常见的XML解析方式有如下两种

1.DOM:

????????要求解析器将整个XML文件全部加载到内存中,生成一个Document对象

????????????????1.优点:元素和元素之间保留结构、关系,可以针对元素进行增删查改操作

????????????????2.缺点:如果XML文件过大,可能会导致内存溢出

2.SAX:

????????是一种速度更快,更加高效的解析方式。它是逐行扫描,边扫描边解析,并且以事件驱动的方式来进行具体的解析,每解析一行都会触发一个事件

????????????????1.优点:不会出现内存溢出的问题,可以处理大文件

????????????????2.缺点:只能读,不能写

????????解析器就是根据不同的解析方式提供具体的实现,为了方便开发人员来解析XML,有一些方便操作的类库。

dom4j:比较简单的XML解析的类库

Jsoup:功能强大的DOM方式解析的类库,尤其对HTML的解析更加方便

本人的项目结构,一点要注意XML路径!!

使用dom4j解析user.xml

  1. 创建解析器对象
  2. 使用解析器对象读取XML文档生成Document对象
  3. 根据Document对象获取xML的元素(标签)信息

Dom4j重要的APl说明

????????org.dom4j.Document常用方法

Element getRootElement();//获取xML文件的根节点

????????org.dom4j.Element的常用方法

String getName(); //返回标签的名称
List<Element> elements(); //获取标签的子标签

String attributeValue(String name);//获取指定属性名称的属性值

String getText();//获取标签的文本

String elementText(Stringname);//获取措定名称的子标签的文本

完整代码

package com.itheima.demo.dom4j;

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

import java.util.List;

/**
 * dom4j解析用户xml测试
 *
 * @author YZH
 * @date 2023/12/20
 */
public class Dom4jParseUserXmlTest {
    public static void main(String[] args) {
        // 创建解析器对象
        SAXReader saxReader = new SAXReader();
        try {
            // 一定要注意路径!!!吃过亏
            Document document = saxReader.read(Dom4jParseUserXmlTest.class.getClassLoader().getResource("static/user.xml"));
            Element rootElement = document.getRootElement();
            System.out.println("1.----->user.xml根节点名字:"+rootElement.getName());
            System.out.println("------------------------");
            System.out.println("2.----->获取根标签users的子标签列表");
            List<Element> usersSubElementList = rootElement.elements();
            for (Element userElement : usersSubElementList) {
                System.out.println("users标签的子标签的名字是:"+userElement.getName());
                System.out.println("users标签的子标签的id属性值是:"+userElement.attributeValue("id"));
                System.out.println("users标签的子标签的country属性值是:"+userElement.attributeValue("country"));

                System.out.println("------------------");
                System.out.println("3.----->获取user的子标签列表");
                List<Element> userSubElementList = userElement.elements();
                for (Element userSubelement : userSubElementList) {
                    System.out.println("user标签下的子标签名字是:"+userSubelement.getName());
                    System.out.println("user标签下的子标签文本是:"+userSubelement.getText());
                }
            }
            // 获取users标签的第一个user标签
            Element firstUserElement = rootElement.element("user");
            // 第一个user标签的子标签password文本
            String password = firstUserElement.elementText("password");
            System.out.println(password);
        } catch (DocumentException e) {
            e.printStackTrace();
        }
    }
}

?运行后结果:

1.----->user.xml根节点名字:users
------------------------
2.----->获取根标签users的子标签列表
users标签的子标签的名字是:user
users标签的子标签的id属性值是:TB10001
users标签的子标签的country属性值是:Chinese
------------------
3.----->获取user的子标签列表
user标签下的子标签名字是:id
user标签下的子标签文本是:10001
user标签下的子标签名字是:name
user标签下的子标签文本是:admin
user标签下的子标签名字是:password
user标签下的子标签文本是:111111
user标签下的子标签名字是:salary
user标签下的子标签文本是:salary > 15000 & salary < 30000
users标签的子标签的名字是:user
users标签的子标签的id属性值是:TB10002
users标签的子标签的country属性值是:Chinese
------------------
3.----->获取user的子标签列表
user标签下的子标签名字是:id
user标签下的子标签文本是:10002
user标签下的子标签名字是:name
user标签下的子标签文本是:tonny
user标签下的子标签名字是:password
user标签下的子标签文本是:666666
user标签下的子标签名字是:salary
user标签下的子标签文本是:salary > 15000 & salary < 3000
111111

进程已结束,退出代码为 0

3.dom4j结合XPath解析XML

XPath可以使用路径表达式来选取XML文档中的元素或者属性节点,节点是沿着路径来选取的。

XPath的官方文档地址XPath 教程 (zvon.org)

dom4j集成XPath

maven下载依赖

<!-- https://mvnrepository.com/artifact/jaxen/jaxen -->
        <dependency>
            <groupId>jaxen</groupId>
            <artifactId>jaxen</artifactId>
            <version>2.0.0</version>
        </dependency>

dom4j提供基于XPath的API

Document/Element关于XPath的api

????????

Node selectSingleNode(String xpathExpression); //根据xPath表达式获取单个标签(元素/节点)

List<Node> selectNodes(String xpathExpression); //根据xPath表达式获取多个标签(元素/节点)

XPath的语法

  • 绝对路径方式,以/开头的路径表示绝对路径,绝对路径是从根元素开始写。例如/元素/子元素/子子元素..
  • 相对路径方式:相对于当前节点的元素继续查找的节点,不以/开头,../表示上一个元素,./表示当前元素
  • 全文搜索路径方式:例如//子元素,//子元素//子子元素,//子元素/子子元素//表示无论中间有多少层,直接获取所有子元素所有满足条件的元素/表示只找一层
  • 语(条件筛选)方式例如//元素[@attr1='value]

完整代码

package com.itheima.demo.dom4j;

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

import java.util.List;

public class Dom4jXPathParseUserXmlTest {
    public static void main(String[] args) {
        SAXReader saxReader = new SAXReader();
        try {
            Document document = saxReader.read(Dom4jParseUserXmlTest.class.getClassLoader().getResource("user.xml"));
            System.out.println("1.------>使用绝对路径方式查找元素");
            // Node继承Element,也可以换一种写法
            // Node selectSingleNode = document.selectSingleNode("/users/user/password");
            Element element = (Element)document.selectSingleNode("/users/user/password");
            // 获取密码
            String password = element.getText();
            System.out.println("第一个用户的密码是:"+password);

            System.out.println("2.------>使用相对路径方式查找元素");
            Element node =(Element) element.selectSingleNode("../salary");
            System.out.println(node.getText());

            System.out.println("3.------>使用相对路径方式查找元素");
            System.out.println("获取所有ID元素的文本");
            List<Node> idNodeList = document.selectNodes("//id");
            for (Node node1 : idNodeList) {
                Element idElement = (Element) node1;
                System.out.println(idElement.getText());
            }
            System.out.println("4.------>谓语(条件筛选)方式查找元素");
            System.out.println("获取user id属性为TB10001的用户属性信息");
            Element TB10001IDElement = (Element)document.selectSingleNode("//user[@id='TB10001']");
            List<Element> elementList = TB10001IDElement.elements();
            for (Element userSubElement : elementList) {
                System.out.println("user子标签的名称"+userSubElement.getName());
                System.out.println("user子标签的文本"+userSubElement.getText());
            }
        } catch (DocumentException e) {
            throw new RuntimeException(e);
        }

    }
}

运行后结果:?

C:\Users\YZH\.jdks\openjdk-17.0.1\bin\java.exe "-javaagent:D:\IDEA\IntelliJ IDEA 2023.1\lib\idea_rt.jar=63970:D:\IDEA\IntelliJ IDEA 2023.1\bin" -Dfile.encoding=UTF-8 -classpath D:\黑马下半\huizhi-learning\maven_java\target\test-classes;D:\黑马下半\huizhi-learning\maven_java\target\classes;D:\maven-repository\org\junit\jupiter\junit-jupiter-api\5.9.2\junit-jupiter-api-5.9.2.jar;D:\maven-repository\org\opentest4j\opentest4j\1.2.0\opentest4j-1.2.0.jar;D:\maven-repository\org\junit\platform\junit-platform-commons\1.9.2\junit-platform-commons-1.9.2.jar;D:\maven-repository\org\apiguardian\apiguardian-api\1.1.2\apiguardian-api-1.1.2.jar;D:\maven-repository\org\dom4j\dom4j\2.1.4\dom4j-2.1.4.jar;D:\maven-repository\jaxen\jaxen\2.0.0\jaxen-2.0.0.jar com.itheima.demo.dom4j.Dom4jXPathParseUserXmlTest
1.------>使用绝对路径方式查找元素
第一个用户的密码是:111111
2.------>使用相对路径方式查找元素
salary > 15000 & salary < 30000
3.------>使用相对路径方式查找元素
获取所有ID元素的文本
10001
10002
4.------>谓语(条件筛选)方式查找元素
获取user id属性为TB10001的用户属性信息
user子标签的名称id
user子标签的文本10001
user子标签的名称name
user子标签的文本admin
user子标签的名称password
user子标签的文本111111
user子标签的名称salary
user子标签的文本salary > 15000 & salary < 30000

进程已结束,退出代码为 0

XML文件

<?xml version="1.0" encoding="utf-8" ?>
<!--<!DOCTYPE users  SYSTEM "user.dtd">-->
<users>
    <user id ="TB10001" country="Chinese">
        <id>10001</id>
        <name>admin</name>
        <password>111111</password>
    <!--    &用&amp;替代,<用&lt;替代-->
        <salary>salary > 15000 &amp; salary &lt; 30000</salary>
    </user>
    <user id ="TB10002" country="Chinese" source="PC">
        <id>10002</id>
        <name>tonny</name>
        <password>666666</password>
        <!--    &用&amp;替代,<用&lt;替代-->
        <salary>salary > 15000 &amp; salary &lt; 3000</salary>
    </user>
</users>

文章来源:https://blog.csdn.net/YingHuaBuRuTa/article/details/135103127
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。