Java – DOM4J解析XML文件[通俗易懂]

Java – DOM4J解析XML文件[通俗易懂]XML简单理解和解析

大家好,又见面了,我是你们的朋友全栈君。

1. XML文档说明

文档声明

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
1. <?xml ?>: 文档声明,必须位于第一行
2. version属性:xml文档的版本,必须有
3. encoding属性:字符集编码,非必须
4. standalone属性:是否独立(no 依赖外部文件),非必须

约束

在XML技术里,可以编写一个文档来约束一个XML文档的书写规范,这称之为XML约束。
常见的xml约束:DTD、Schema(XSD)
<!DOCTYPE HTMLPUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<note
	xmlns="http://www.w3school.com.cn"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.w3school.com.cn note.xsd">

元素

元素(标签) element
    1.举例: <bean></bean>
    2.普通元素的结构开始标签、元素体、结束标签组成。例如:<name>zhangsan</name>
	2.元素体:元素体可以是元素,也可以是文本,例如:<b><a>你好</a></b>
	3.空元素:空元素只有开始标签,而没有结束标签,但元素必须自己闭合,例如:<c/>
	4.元素命名:
        (1)区分大小写
		(2)不能使用空格,不能使用冒号:
		(3)不建议以XML、xml、Xml开头
    5.格式化良好的XML文档,必须只有一个根元素

属性

1.举例: <bean id="" className="">
2.属性是元素的一部分,它必须出现在元素的开始标签中
3. 属性的定义格式:属性名=属性值,其中属性值必须使用单引或双引
4.一个元素可以有0~N个属性,但一个元素中不能出现同名属性
5.属性名不能使用空格、冒号等特殊字符,且必须以字母开头

转义字符

<  	&lt;
>	&gt;
"	&quot;
'	&apos;
&	&amp;

2. XML解析

2.1 常见的解析方式

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

1.DOM:要求解析器把整个XML文档装载到内存,并解析成一个Document对象。
    (1)优点:元素与元素之间保留结构关系,故可以进行增删改查操作。
	(2)缺点:XML文档过大,可能出现内存溢出显现。
2.SAX:
    是一种速度更快,更有效的方法。它逐行扫描文档,一边扫描一边解析。
    并以事件驱动的方式进行具体解析,每执行一行,都将触发对应的事件。(了解)
    (1)优点:处理速度快,可以处理大文件
	(2)缺点:只能读,逐行后将释放资源。
3.PULL:Android内置的XML解析方式,类似SAX。(了解)

2.2 DOM4J解析xml

  • DOM4J是以dom方式解析。一个Java的XML API,具有性能优异、功能强大和极其易使用的特点,它的性能超过sun公司官方的dom技术.
  • jar包:dom4j-1.6.1.jar
<?xml version="1.0" encoding="UTF-8" ?>
<students>
    <student id="1">
        <name>张三</name>
        <age>18</age>
        <gender></gender>
    </student>
    <student id="2">
        <name>李四</name>
        <age>17</age>
        <gender></gender>
    </student>
    <student id="3">
        <name>王五</name>
        <age>22</age>
        <gender></gender>
    </student>
</students>
package xml_parse_dom4j;

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

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

public class Demo01 { 
   
    public static void main(String[] args) throws DocumentException, IOException { 
   
        //1.通过类加载器获取资源输入流对象
        InputStream inputStream = Demo01.class.getClassLoader().getResourceAsStream("students.xml");

        //2.创建org.dom4j.io包中的SAXReader对象
        SAXReader saxReader = new SAXReader();

        Document document = null;

        try (inputStream) { 
   
            //3. 读取输入流 得到文档对象
            document = saxReader.read(inputStream);
        }

        //4.拿到根元素
        Element rootElement = document.getRootElement();

        //5. 得到内部元素集合
        List<Element> elements = rootElement.elements();

        //6. 遍历 属性,值
        for (Element element : elements) { 
   

            String s = null;

            String name = element.getName();//拿到元素名
            String id = element.attributeValue("id");//拿到元素的属性的值

            s = "{" + name + ": " + "属性id=" + id;

            List<Element> chileElements = element.elements();//元素的子元素集合
            for (Element chileElement : chileElements) { 
   //遍历
                String chileElementName = chileElement.getName();
                String chileElementContent = chileElement.getText();//得到子元素内容

                s += "\n\t\t" + chileElementName + "=" + chileElementContent + "}";
            }
            System.out.println(s);
        }
    }
}

在这里插入图片描述

2.3 XPath表达式解析XML

  • 由于DOM4J在解析XML时只能一层一层解析,所以当XML文件层数过多时使用会很不方便,结合XPATH就可以直接获取到某个元素。
  • 引入jar包:jaxen-1.1.6.jar
  • 在dom4j里面提供了两个方法,用来支持xpath
List<Node> selectNodes("xpath表达式"),用来获取多个节点
Node selectSingleNode("xpath表达式"),用来获取一个节点

xpath表达式

"nodename"				当前节点下的<nodename>元素节点
"/nodename" 			<文档节点>下的<nodename>元素节点
"//nodename"			全局匹配下的所有<nodename>元素节点
"/nodename1/nodename2"	<文档节点>下的<nodename1>下的<nodename2>元素节点
"/nodename1//nodename2"	<文档节点>下的<nodename1>下的(子、孙...)所有<nodename2>元素节点
"//@attribubeName"		全局匹配下的所有<attribubeName>属性节点
"/nodename1/nodename2[@id='1']" <文档节点>下的<nodename1>下的属性id=1<nodename2>元素节点

XPath 语法|菜鸟教程 先别看中文解释,只看表达式,照着练练理解,再理解它的中文解释。

package xml_parse_xpath;

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

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

public class Demo02 { 
   
    public static void main(String[] args) throws DocumentException, IOException { 
   

        //1.通过类加载器获取资源输入流对象
        InputStream inputStream = Demo02.class.getClassLoader().getResourceAsStream("students.xml");

        //2.创建org.dom4j.io包中的SAXReader对象
        SAXReader saxReader = new SAXReader();

        Document document = null;
        try (inputStream) { 
   
            //3. 读取输入流 得到文档对象
            document = saxReader.read(inputStream);
        }
        Element studentsElement = document.getRootElement();//<students>
        Element studentElement = (Element) studentsElement.elements().get(0); //第一个<student>

        //1. "nodename" 查询当前节点下的所有 "nodename" 子节点
        System.out.println("\"nodename\"");
        System.out.println(document.selectNodes("students")); //查询当前节点(document 文档节点)下的students子节点
        //out: [org.dom4j.tree.DefaultElement@276438c9 [Element: <students attributes: []/>]]
        System.out.println(studentsElement.selectNodes("students")); //查询<students>下的<students>
        //out: []
        System.out.println(studentElement.selectNodes("students")); //查询<student>下的students子节点
        //out: []
        System.out.println("==========================================================================");

        //2. "/nodename" 查询<文档>节点下的<nodename>子节点,不管当前节点是谁 / 都从文档节点查
        System.out.println("\"/nodename\"");
        System.out.println(document.selectNodes("/students"));//查询<文档>下的<students>
        //out: [org.dom4j.tree.DefaultElement@276438c9 [Element: <students attributes: []/>]]
        System.out.println(studentsElement.selectNodes("/students")); //查询<文档>下的<students>
        //out: [org.dom4j.tree.DefaultElement@276438c9 [Element: <students attributes: []/>]]
        System.out.println(studentElement.selectNodes("/students")); //查询<文档>下的<students>
        //out: [org.dom4j.tree.DefaultElement@276438c9 [Element: <students attributes: []/>]]
        System.out.println("==========================================================================");

        //3. "//nodename" 查询所有的<nodename>节点,全局匹配
        System.out.println("\"//nodename\"");
        System.out.println(document.selectNodes("//name"));
        //out: [org.dom4j.tree.DefaultElement@701fc37a [Element: <name attributes: []/>], org.dom4j.tree.DefaultElement@31206beb [Element: <name attributes: []/>], org.dom4j.tree.DefaultElement@21a947fe [Element: <name attributes: []/>], org.dom4j.tree.DefaultElement@71248c21 [Element: <name attributes: []/>]]
        System.out.println(studentsElement.selectNodes("//name"));
        //out: [org.dom4j.tree.DefaultElement@701fc37a [Element: <name attributes: []/>], org.dom4j.tree.DefaultElement@31206beb [Element: <name attributes: []/>], org.dom4j.tree.DefaultElement@21a947fe [Element: <name attributes: []/>], org.dom4j.tree.DefaultElement@71248c21 [Element: <name attributes: []/>]]
        System.out.println(studentElement.selectNodes("//name"));
        //out: [org.dom4j.tree.DefaultElement@701fc37a [Element: <name attributes: []/>], org.dom4j.tree.DefaultElement@31206beb [Element: <name attributes: []/>], org.dom4j.tree.DefaultElement@21a947fe [Element: <name attributes: []/>], org.dom4j.tree.DefaultElement@71248c21 [Element: <name attributes: []/>]]
        System.out.println("==========================================================================");

        //4. "nodename1/nodename2" 查询当前节点下的<nodename1>下的<nodename2>节点
        System.out.println("\"nodename1/nodename2\"");
        System.out.println(document.selectNodes("students/student"));
        //out: [org.dom4j.tree.DefaultElement@70beb599 [Element: <student attributes: [org.dom4j.tree.DefaultAttribute@15d9bc04 [Attribute: name id value "1"], org.dom4j.tree.DefaultAttribute@473b46c3 [Attribute: name u value "first"]]/>], org.dom4j.tree.DefaultElement@11e21d0e [Element: <student attributes: [org.dom4j.tree.DefaultAttribute@516be40f [Attribute: name id value "2"]]/>], org.dom4j.tree.DefaultElement@37574691 [Element: <student attributes: [org.dom4j.tree.DefaultAttribute@3c0a50da [Attribute: name id value "3"], org.dom4j.tree.DefaultAttribute@646be2c3 [Attribute: name uid value "003"]]/>], org.dom4j.tree.DefaultElement@16267862 [Element: <student attributes: [org.dom4j.tree.DefaultAttribute@797badd3 [Attribute: name id value "4"], org.dom4j.tree.DefaultAttribute@77be656f [Attribute: name uid value "last"]]/>]]
        System.out.println(studentsElement.selectNodes("students/student"));
        //[]
        System.out.println(studentElement.selectNodes("students/student"));
        //[]
        System.out.println("==========================================================================");

        //5. "nodename1//nodename2" 查询当前节点下的<nodename1>后代中所有<nodename2>节点 , 在<nodename1>下全局匹配<nodename2>
        System.out.println("\"nodename1//nodename2\"");
        System.out.println(document.selectNodes("students//name"));
        //[org.dom4j.tree.DefaultElement@701fc37a [Element: <name attributes: []/>], org.dom4j.tree.DefaultElement@31206beb [Element: <name attributes: []/>], org.dom4j.tree.DefaultElement@21a947fe [Element: <name attributes: []/>], org.dom4j.tree.DefaultElement@71248c21 [Element: <name attributes: []/>]]
        System.out.println(studentsElement.selectNodes("student//name")); //<students> -> <students> -> <name>
        //[org.dom4j.tree.DefaultElement@701fc37a [Element: <name attributes: []/>], org.dom4j.tree.DefaultElement@31206beb [Element: <name attributes: []/>], org.dom4j.tree.DefaultElement@21a947fe [Element: <name attributes: []/>], org.dom4j.tree.DefaultElement@71248c21 [Element: <name attributes: []/>]]
        System.out.println(studentElement.selectNodes("//name"));
        //[org.dom4j.tree.DefaultElement@701fc37a [Element: <name attributes: []/>], org.dom4j.tree.DefaultElement@31206beb [Element: <name attributes: []/>], org.dom4j.tree.DefaultElement@21a947fe [Element: <name attributes: []/>], org.dom4j.tree.DefaultElement@71248c21 [Element: <name attributes: []/>]]
        System.out.println("==========================================================================");

        //6. "//@id" 全局匹配属性名为id的属性节点
        System.out.println("\"//@id\"");
        System.out.println(document.selectNodes("//@id"));
        //out: [org.dom4j.tree.DefaultAttribute@15d9bc04 [Attribute: name id value "1"], org.dom4j.tree.DefaultAttribute@516be40f [Attribute: name id value "2"], org.dom4j.tree.DefaultAttribute@3c0a50da [Attribute: name id value "3"], org.dom4j.tree.DefaultAttribute@797badd3 [Attribute: name id value "4"]]
        System.out.println(studentsElement.selectNodes("//@id"));
        //out: [org.dom4j.tree.DefaultAttribute@15d9bc04 [Attribute: name id value "1"], org.dom4j.tree.DefaultAttribute@516be40f [Attribute: name id value "2"], org.dom4j.tree.DefaultAttribute@3c0a50da [Attribute: name id value "3"], org.dom4j.tree.DefaultAttribute@797badd3 [Attribute: name id value "4"]]
        System.out.println(studentElement.selectNodes("//@id"));
        //out: [org.dom4j.tree.DefaultAttribute@15d9bc04 [Attribute: name id value "1"], org.dom4j.tree.DefaultAttribute@516be40f [Attribute: name id value "2"], org.dom4j.tree.DefaultAttribute@3c0a50da [Attribute: name id value "3"], org.dom4j.tree.DefaultAttribute@797badd3 [Attribute: name id value "4"]]
        System.out.println(studentElement.selectNodes("@id"));// <student> -> id属性节点
        //out: [org.dom4j.tree.DefaultAttribute@15d9bc04 [Attribute: name id value "1"]]
        System.out.println("==========================================================================");

        //7. "/students/student[age>18]" //得到age大于18的student元素节点数组
        System.out.println(document.selectNodes("/students/student[age>18]"));
        //out: [org.dom4j.tree.DefaultElement@37574691 [Element: <student attributes: [org.dom4j.tree.DefaultAttribute@3c0a50da [Attribute: name id value "3"], org.dom4j.tree.DefaultAttribute@646be2c3 [Attribute: name uid value "003"]]/>], org.dom4j.tree.DefaultElement@16267862 [Element: <student attributes: [org.dom4j.tree.DefaultAttribute@797badd3 [Attribute: name id value "4"], org.dom4j.tree.DefaultAttribute@77be656f [Attribute: name uid value "last"]]/>]]
        System.out.println(studentsElement.selectNodes("/students/student[age>18]"));
        //out: [org.dom4j.tree.DefaultElement@37574691 [Element: <student attributes: [org.dom4j.tree.DefaultAttribute@3c0a50da [Attribute: name id value "3"], org.dom4j.tree.DefaultAttribute@646be2c3 [Attribute: name uid value "003"]]/>], org.dom4j.tree.DefaultElement@16267862 [Element: <student attributes: [org.dom4j.tree.DefaultAttribute@797badd3 [Attribute: name id value "4"], org.dom4j.tree.DefaultAttribute@77be656f [Attribute: name uid value "last"]]/>]]
        System.out.println(studentElement.selectNodes("/students/student[age>18]"));
        //out: [org.dom4j.tree.DefaultElement@37574691 [Element: <student attributes: [org.dom4j.tree.DefaultAttribute@3c0a50da [Attribute: name id value "3"], org.dom4j.tree.DefaultAttribute@646be2c3 [Attribute: name uid value "003"]]/>], org.dom4j.tree.DefaultElement@16267862 [Element: <student attributes: [org.dom4j.tree.DefaultAttribute@797badd3 [Attribute: name id value "4"], org.dom4j.tree.DefaultAttribute@77be656f [Attribute: name uid value "last"]]/>]]
    }
}

3. 解析XML并封装到类中

  • 解析bean.xml文件 并 封装到Teacher类中
  • bean.xml文件
<?xml version="1.0" encoding="UTF-8" ?>
<bean className="xml_parse_task.domain.Teacher">
    <property name="name" value="张三"></property>
    <property name="age" value="16"></property>
    <property name="salary" value="88888.88"></property>
</bean>
  • 实体类Teacher
package xml_parse_task.domain;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class Teacher { 
   
    private String name;
    private int age;
    private double salary;
}
  • 过程代码
package xml_parse_task;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import xml_parse_task.domain.Teacher;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;

public class Demo02 { 
   
    public static void main(String[] args) throws DocumentException, IOException, NoSuchFieldException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchMethodException { 
   
        method();
    }

    public static void method() throws DocumentException, IOException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException { 
   
        //解析xml dom4j+XPath
        InputStream inputStream = Demo02.class.getClassLoader().getResourceAsStream("bean.xml");
        SAXReader saxReader = new SAXReader();
        Document document = saxReader.read(inputStream);
        inputStream.close();
        List<Element> list = document.selectNodes("/bean/property");

        //Teacher.class 拿到字节码文件
        Class<Teacher> teacherClass = Teacher.class;
        //Teacher teacher = teacherClass.newInstance();
        //得到空参构造器
        Constructor<Teacher> constructor = teacherClass.getConstructor();
        //创新Teacher对象
        Teacher teacher = constructor.newInstance();

        for (Element element : list) { 
   
            //根据name 获取字段
            String name = element.attributeValue("name");
            String value = element.attributeValue("value");

            String mName = "set" + name.substring(0, 1).toUpperCase() + name.substring(1);
            System.out.println(mName);

            Field field = teacherClass.getDeclaredField(name);
            Class<?> type = field.getType();
            System.out.println(type);
            if (type == int.class) { 
   
                Method method = teacherClass.getMethod(mName,int.class);
                int i = Integer.parseInt(value);
                method.invoke(teacher, i);
            } else if (type == double.class) { 
   
                Method method = teacherClass.getMethod(mName,double.class);
                double d = Double.parseDouble(value);
                method.invoke(teacher, d);
            } else if(type == String.class){ 
   
                Method method = teacherClass.getMethod(mName,String.class);
                method.invoke(teacher, value);
            }else{ 
   
                System.out.println("方法参数参数啥也不是");
            }
        }
        System.out.println(teacher);
    }
}

4. 参考资料

W3C

菜鸟教程XPath 语法

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/152040.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • oracle关闭服务命令_oracle数据库命令

    oracle关闭服务命令_oracle数据库命令一、srvctl命令的使用srvctl是servicecontrol的缩写,基本的用法是srvctl[],使用srvctl命令,可以对rac各个节点的数据库实例,asm实例和监听器等进行管理,挺方便的工具oracle@rac2~]$srvctlUsage:srvctl[]command:enable|disable|start|stop|relocate|status|add…

  • 操作系统栈溢出检测之ucosII篇[通俗易懂]

    操作系统栈溢出检测之ucosII篇[通俗易懂]操作系统栈溢出检测之uc/osII篇Author              :     DavidLin(林鹏)E-mail               :       linpeng1577@gmail.com                                    linpeng1577@163.com 158820224344@163.co

  • 安装pyodbc_编程python是什么

    安装pyodbc_编程python是什么1、连接数据库pipinstallpyodbc成功后就可以用了首先要importpyodbc1)直接连接数据库和创建一个游标(cursor)cnxn=pyodbc.connect(‘DRIVER={SQLServer};SERVER=localhost;DATABASE=testdb;UID=me;PWD=pass’)cursor=cnxn.cursor()2)使用DSN连接。通常DSN连接并不需要密码,还是需要提供一个PSW的关键字。cnxn=pyodb

  • MATLAB GUI设计之弹出式菜单的使用

    MATLAB GUI设计之弹出式菜单的使用弹出式菜单在MATLABGUI设计中常常出现。比如串口助手、绘制图形等经常见到弹出式菜单如下图所示:使用方法:一、准备工作1、从MATLABGUIDE中拖出一个弹出式菜单2、双击这个弹出式菜单,出现检查器:将注意力放在途中红线位置处,点击string处的图标将其中的内容修改为你想要显示的内容:tag处的内容修改为自己想管这个弹出式菜单的名字。这里就按照原来

  • matlab在指定figure中画图_matlab保存fig为图片语句

    matlab在指定figure中画图_matlab保存fig为图片语句转载:http://www.ilovematlab.cn/thread-296430-1-1.html最近看了一些用matlab对图形图片进行保存的帖子和资源,关于图像保存的方法给大家分享一下这些方法是大家所使用方法的一个总结.如今常用的方法有三种printf,imwrite,saveas下面分别介绍一下:imwritemwrite将图像数据写成图像文件,一般用

  • 服务器硬件基础知识

    服务器硬件基础知识服务器的概述计算机的硬件主要有主机和输入/输出设备。主机包括机箱,电源,主板,CPU(中央处理器),内存,显卡,声卡,网卡,硬盘,光驱等。输入/输出包括显示器,键盘,鼠标,音箱,摄像头,打印机和扫描仪等。服务器服务器是指在网络环境下运行相应的应用软件,为网上用户提供共享信息资源和各种服务的一直高性能计算机。服务器的选择:处理器性能,I/O性能,管理性,可靠性,扩展性。同样…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号