Dom4j解析XML(详解)-程序员宅基地

技术标签: java  xml  intellij-idea  

1.XML解析的方式介绍

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

1.DOM解析

DOM解析要求解析器将整个XML文件全部加载到内存中,生成一个Document对象。
1.优点:元素和元素之间保留结构,关系,可以针对元素进行增删改查操作。
2.缺点:如果XML文件过大,可能会导致内存溢出。

2.SAX解析

SAX解析是一种更加高效的解析方式。它是逐行扫描,边扫描边解析,并且以时间驱动的方式进行具体的解析,每解析一行都会触发一个事件。
1.优点:不会出现内存溢出的问题,可以处理大文件。
2.缺点:只能读,不能写。

3.常见的解析XML类库

解析器就是根据不同的解析方式提供具体的实现,为了方便开发人员来解析XML,有一些方便操作的类库。具体如下所示:
1.dom4j:比较简单的XML解析类库;
2.Jsoup:功能强大的DOM方式解析的类库,尤其对HTML的解析更加方便,所以可以使用Jsoup来爬取网页的数据。

2.使用dom4j解析XML

1.创建普通的Maven项目

打开IDEA编译器,在导航栏选择文件,接下来点击新建 ,然后选择项目。点击后出现如图所示的界面:
在这里插入图片描述
选择创建一个普通的Maven项目,直接点击下一步即可。接下来自定义项目的名称,位置以及工作坐标。具体如下所示:
在这里插入图片描述
点击完成后,IDEA便开始加载项目。

2.导入dom4j的依赖

在加载后的项目下,找到pom.xml文件,将依赖导入其中,具体依赖如下所示:

<dependencies>
            <dependency>
                <groupId>org.dom4j</groupId>
                <artifactId>dom4j</artifactId>
                <version>2.1.1</version>
            </dependency>
    </dependencies>

3.使用dom4j解析user.xml

使用dom4j解析user.xml的步骤如下所示:
在项目的resource目录下创建user.xml文件;
在下面user.xml文件中,users是根标签,根标签是全局唯一的;
在根标签下有两个user子标签,每一个user子标签都有两个属性,一个是country,另一个是source;在user标签下同样有三个子标签,分别是id,name以及password标签,具体如下所示:
1.编写user.xml文件

<?xml version="1.0" encoding="UTF-8" ?>
<!--文档声明
    XML的文档声明是可选的,也就是可以不写,但是日常生活开发中大家都会写
    XML文档声明如果写了,它必须放在XML文档的第一行第一列,必须以<?xml开头 以?>结尾,而且必须包含两个属性
    一个是version,表示XML的版本
    一个是encoding,表示XML的编码
-->
<!--
    元素是XML的重要组成部分,元素也被称为标签
    每个XML文件必须要有一个根标签
    标签有开始标签和结束标签组成,开始标签和结束标签可以写标签,也可以是文本字符串
    标签可以嵌套使用,但是不能随便嵌套
    标签名必须准守命名规则和命名规范
-->
<!--
    属性是标签的组成部分,属性只能定义在开始标签中,不能定义在结束标签中
    属性定义的格式:属性名=属性值,属性值需要使用""包含起来
    开始标签中可以定义多个属性,但是多个属性的属性名不能相同
    属性名必须准守命名规则和命名规范
-->
<users>
    <user id="10001" country="Chinese" source="Android">
        <id>10001</id>
        <name>admin</name>
        <password>111111</password>
    </user>

    <user id="10002" country="Chinese" source="ios">
        <id>10002</id>
        <name>tony</name>
        <password>666666</password>
    </user>

</users>

2.创建解析器对象

//创建解析器对象
        SAXReader saxReader=new SAXReader();

3.使用解析器对象读取XML文档生成Document对象

//根据user.xml文档生成Document对象
Document document = saxReader.read(Dom4jParseUserXmlTest.class.getClassLoader().getResource("users.xml"));

4.根据Document对象获取XML的元素(标签)信息
Dom4j的常用API说明:

方法 操作
Element getRootElement(); 获取XML文件的根节点
String getName(); 返回标签的名称
List < Element > elements(); 获取标签所有的子标签
String arrtributeVallue(String name) ; 获取指定属性名称的属性值
String getText(); 获取标签的文本
String elementText(String name); 获取指定名称的子标签的文本,返回子标签文本的值

具体的Dom4j解析的具体测试代码如下所示:

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

import java.util.List;

public class Dom4jParseUserXmlTest {
    
    public static void main(String[] args) {
    
        //创建解析器对象
        SAXReader saxReader=new SAXReader();
        try {
    
            Document document = saxReader.read(Dom4jParseUserXmlTest.class.getClassLoader().getResource("users.xml"));
            Element rootElement = document.getRootElement();
            System.out.println("1.------->users.xml文件的根节点的名字是:"+rootElement.getName());

            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("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.attributeValue("password");
            System.out.println(password);
        } catch (DocumentException e) {
    
            e.printStackTrace();
        }
    }
}

3.dom4j结合XPath解析XML

1.Dom4j集成XPath

在pom.xml导入Xpath对应的依赖即可,具体如下所示:

<dependency>
            <groupId>jaxen</groupId>
            <artifactId>jaxen</artifactId>
            <version>1.2.0</version>
</dependency>

2.Dom4j提供基于XPath的API

方法 操作
Node selectSingleNode(String xpathExpression); 根据XPath表达式获取单个标签(元素/节点)
List < Node > selectNodes(String xpathExpression) 根据XPath表达式获取多个标签(元素/节点)

3.XPath的语法

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

具体对应的每一种方式的Java测试程序如下所示:

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(Dom4jXPathParseUserXmlTest.class.getClassLoader().getResource("users.xml"));
            //拿到第一个用户的密码
            System.out.println("1.------>使用绝对路径方式来查找元素");
            Element element = (Element) document.selectSingleNode("/users/user/password");
            String password = element.getText();
            System.out.println(password);

            System.out.println("2.------>使用相对路径查找元素");
            //element是当前获取的password元素
            Element name = (Element) element.selectSingleNode("../name");
            System.out.println("第一个用户的姓名为"+name.getText());

            System.out.println("3.------>使用全局搜索的方式");
            //获取所有的id元素的文本
            List<Node> idNodeList = document.selectNodes("//id");
            for (Node node : idNodeList) {
    
                Element idElement=(Element) node;
                System.out.println(idElement.getText());
             }
            System.out.println("4.------>谓语形式");
            //获取id=10002的用户信息
            Element idElement = (Element) document.selectSingleNode("//user[@id='10002']");
            List<Element> elements = idElement.elements();
            for (Element element1 : elements) {
    
                System.out.println(element1.getName()+"="+element1.getText());
            }
        } catch (DocumentException e) {
    
            e.printStackTrace();
        }
    }
}

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_51447436/article/details/124754572

智能推荐

Java关于子类对父类私有方法覆盖的问题_子继承父类时,覆盖了继承来的方法,并且方法是空的-程序员宅基地

文章浏览阅读1.2w次,点赞11次,收藏18次。最近在学习到Java的继承和多态时遇到了这样的一个问题:关于继承链中子类对父类的私有方法是否可以覆盖的问题,在此记录一下自己对这个问题解决以后的一些心得。_子继承父类时,覆盖了继承来的方法,并且方法是空的

易语言之X64位内存注入DLL技术_易语言dll注入-程序员宅基地

文章浏览阅读7.1k次,点赞2次,收藏4次。说到易语言对64位进程注入dll方面,虽然我们Game-EC模块里面已经有对64位程序进行注入dll的功能了,最近研究开发了另外一种对64位程序进程进行注入dll的功能,今天给大家带来的是最近开发的新功能里面其中一个64位内存注入dll,也是属于64位游戏辅助开发方面的。因为之前有不少开发64位的人建议我,希望能出个隐,藏64位dll的功能就好了,因为注入游戏dll经常遇见被枚举dll方法就能检测到是否有第三方dll(也就是的辅助dll)注入到了进程,被游戏检测到使用辅助。所以我这段时间在新版模块里面_易语言dll注入

59、Php使用mysqli与mysql交互(4) 一次执行多条sql语句预处理语句机制_mysql execute stmt可以一次提交多个sql吗-程序员宅基地

文章浏览阅读722次。4)一次性执行多条SQL语句,多个SQL语句用分号隔开 bool mysqli_multi_query ( mysqli $link , string $query );3.预处理语句机制1)准备一个用于执行的SQL语句mysqli_stmt mysqli_prepare ( mysqli $link , string $query );2)将变量作为参数绑定到prepared语句上b..._mysql execute stmt可以一次提交多个sql吗

Qt项目的构建(编译)、运行与调试(三)_qt 编译-程序员宅基地

文章浏览阅读6.1k次,点赞3次,收藏25次。Qt项目的构建(编译)、运行与调试_qt 编译

3台mongodb集群部署_mongo怎么给3台mongos部署一个主入口-程序员宅基地

文章浏览阅读2.7k次,点赞2次,收藏4次。###【在多台机器上执行下面的命令#在所有创建一个xiaoniu普通用户:useradd xiaoniu#为xiaoniu用户添加密码:echo 123456 | passwd --stdin xiaoniu#将xiaoniu添加到sudoersecho "xiaoniu ALL = (root) NOPASSWD:ALL" | tee /etc/sudoers.d/xiaoniu..._mongo怎么给3台mongos部署一个主入口

html 阴影只有两侧,如何仅在左侧和右侧获得阴影-程序员宅基地

文章浏览阅读1k次。经典方法:负向传播CSS box-shadow使用4个参数:h-shadow,v-shadow,blur,spread:box-shadow: 10px 0 8px -8px black;的V-阴影(中古立式阴影)被设置为0。该模糊参数添加渐变效果,而且还增加了对垂直边框(我们想摆脱的一个)一点点影子。负传播会减少所有边界上的阴影:您可以使用它来尝试消除一点垂直阴影,而又不影响一侧的过多阴影(对于..._box-shadow 只要左边阴影

随便推点

李洪强和你一起学习前端之(9)规避脱标,CSS可见性,滑动门案例-程序员宅基地

文章浏览阅读132次。1 复习昨天知识1.1 浮动   特点:    >浮动的元素不占位置(脱标)    >可以将行内元素转化为行内块元素    >块级元素在一行上显示    >设置了浮动的元素,影响其后面的元素   作用:    >解决文字图片环绕问题    >制作网页导航栏    >网页布局   ..._元素脱标屏幕是否可以滑动

微信之 appId 和 appsecret 获取accesstoken_根据 appid、appsecret 获取 app_access_token_json-程序员宅基地

文章浏览阅读2.5k次。代码调用/** * 获access_token * * @return */ public static String getAccessTokenOne(String appId,String appSecret) { String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" _根据 appid、appsecret 获取 app_access_token_json

ViewPager2+TabLayout_viewpager2 tablayout-程序员宅基地

文章浏览阅读8.3k次,点赞6次,收藏33次。ViewPager2+TabLayout_viewpager2 tablayout

Python特殊运算符解释(**/^/%?//)_python*^是什么意思-程序员宅基地

文章浏览阅读1.3w次,点赞11次,收藏18次。Python特殊运算符解释(**/^/%?//)来源:https://stackoverflow.com/questions/15193927/what-do-these-operators-mean本文为翻译加补充话不多说,先上图**表示幂运算>>>9**2 81>>>9**2.0 81.0 #输出格式^表示二进制异或运算如下表(相同..._python*^是什么意思

(转)em重建全过程-程序员宅基地

文章浏览阅读254次。该问题遇到N次,被郁闷N次,特此记录以备不时之需由于n久不用em,而本机在公司使用dhcp自动获取ip,导致ip变化,而使em启动报出ora-12514 DBD ERROR: OCIServerAttach的错误ITPUB个人空间/v:U d5\]|1v9MtK不得不禁用dhcp,分配固定ip并重建em,过程如下:1.删除EMC:\Documents and Settings\..._} j@c ! em|

xsl教程学习笔记-程序员宅基地

文章浏览阅读152次。一 . Hello world 尝试:Hello.xml:<?xml version="1.0" encoding="UTF-8"?>    <?xml-stylesheet type="text/xsl" href="test.xsl"?><FistNode>Hello,World</FistNode>..._xsl教程 csdn