JavaWeb学习-XML系列-4-XML之DOM4J解析

来学习XML文件的解析,不管是度还是写xml文件,第一件事情就是先解析。例如,我们看到很多配置文件是xml,里面有key和value,对应的程序代码就需要去解析xml文件,拿到用户修改的值去更改软件的设置。早期的网站,数据传输很多都是采用xml文件,例如用户请求一个接口,接口返回来就是xml内容,在发相应内容给前端之前,代码是需要解析xml并往里面写入请求之后的数据。

XML解析思想

XML常见的解析方式有DOM和xpath两种,这篇我们主要来看DOM解析。DOM即Document Object Model,文档对象模型),将文档加载进内存,形成一颗dom树(document对象),将文档的各个组成部分封装为一些对象。

DOM解析的优缺点

优点:有了dom树,可以在内存中对dom树进行增删改查操作。
缺点:dom树非常占内存,解析速度慢。例如有1kb的xml文档,转成dom树在内存中可能占用1M内存。

DOM解析可以解析出下面五大结点
Document
Element
Text
Attribute
Comment

上面五个对象,下面代码我们会练习到。

SAX解析
特点:逐行读取,基于事件驱动
优点:不占内存,速度快
缺点:只能读取,不能写

XML常用的解析器
*JAXP:sun公司提供的,支持dom和sax,不好用,几乎没人使用
*JDOM:半路夭折
*DOM4J:dom for java,开源的产品,借鉴了前面两者的优点,避免了缺点,支持dom
使用步骤:
    1.导入dom4j.jar文件
    2.创建解析器 SAXReader reader = new SAXReader()
    3.解析xml获得document对象 Document document = reader.read(url)

DOM4J 下载

浏览器打开https://dom4j.github.io/

这里我下载dom4j-2.1.1,jdk8以上版本可以使用这个版本的DOM4J,下载下来是一个jar,我们把这个添加到项目的build path中去。准备一个student.xml文件,放到项目的根目录下(和src同级)。

<?xml version="1.0" encoding="UTF-8" ?>
<students>
	<student>
		<name>ZS</name>
		<age>18</age>
		<gender>male</gender>
	</student>
	<student>
		<name>LS</name>
		<age>19</age>
		<gender>female</gender>
	</student>

</students>

有了这个xml测试文件,现在我们就可以对照https://dom4j.github.io/ 上面的例子去实现代码。

解析XML文件,得到document对象

package com.anthony.parse;

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

public class DOM4JTest {

	public static void main(String[] args) throws DocumentException {
		
		Document doc = parse("student.xml");
		System.out.println(doc.toString());
	}
	
	public static Document parse(String xmlPath) throws DocumentException {
		SAXReader reader = new SAXReader();
		Document doc = reader.read(xmlPath);
		return doc;		
	}

}

得到的document对象打印出现是一个内存地址。接下来,我们先拿到根元素,然后遍历标签和属性。

遍历标签和属

思路就是先得到根节点,通过根节点可以遍历根节点的第一层子节点,当然如果子节点下还有嵌套子节点,我们程序就写for嵌套就行。这里我们准备的student.xml就两层嵌套标签。我下面的代码是拿到students根节点,然后拿到student这个子节点,然后继续迭代拿到name age gender三个标签,最后通过ele.getStringValue()方法来打印标签的文本内容,也就是我们的value。我们这个xml文件没有写标签的属性和属性值。

package com.anthony.parse;

import java.util.Iterator;

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

public class DOM4JTest {

	public static void main(String[] args) throws DocumentException {
		// get document object
		Document doc = parse("student.xml");
		getElementInfo(doc);
	}
	
	public static Document parse(String xmlPath) throws DocumentException {
		SAXReader reader = new SAXReader();
		Document doc = reader.read(xmlPath);
		return doc;		
	}
	
	public static void getElementInfo(Document doc) {
		//get root element
		Element root = doc.getRootElement();
		
		// iterate through child elements of root
		for(Iterator<Element> it = root.elementIterator(); it.hasNext();) {
			Element element = it.next();
			System.out.println(element.getStringValue());
		}
	}
}

运行结果

                ZS
		18
		male
	

		LS
		19
		female

递归元素

其实上面迭代器方式是很消耗内存,DOM4J网页上说,如果解析一个比较大的xml文档,不建议使用迭代器的方式,而是选择递归的方法。下面来看看递归如何拿到每个元素的文本内容。

package com.anthony.parse;

import java.util.Iterator;

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

public class DOM4JTest {

	public static void main(String[] args) throws DocumentException {
		// get document object
		Document doc = parse("student.xml");
		// get root element
		Element root = doc.getRootElement();
		treeWalk(root);
	}
	
	public static Document parse(String xmlPath) throws DocumentException {
		SAXReader reader = new SAXReader();
		Document doc = reader.read(xmlPath);
		return doc;		
	}
	
	//递归方式,如果节点是元素标签,那么继续递归,如果不是,打印出标签的文本信息
	public static void treeWalk(Element element) {
	    for (int i = 0, size = element.nodeCount(); i < size; i++) {
	        Node node = element.node(i);
	        if (node instanceof Element) {
	            treeWalk((Element) node);
	        } else {
	        	System.out.println(node.getStringValue());
	        }
	    }
	}
}

运行结果


	

		
ZS

		
18

		
male

	

	

		
LS

		
19

		
female

	

运行结果很多空行。

如果我们确定xml文档中根节点下,只需要解析出特定名称的元素的信息,那么上面getElementinfo方法可以修改成这样。

package com.anthony.parse;

import java.util.Iterator;

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

public class DOM4JTest {

	public static void main(String[] args) throws DocumentException {
		// get document object
		Document doc = parse("student.xml");
		getElementInfoWithName(doc);
	}
	
	public static Document parse(String xmlPath) throws DocumentException {
		SAXReader reader = new SAXReader();
		Document doc = reader.read(xmlPath);
		return doc;		
	}
	
	public static void getElementInfo(Document doc) {
		//get root element
		Element root = doc.getRootElement();
		
		// iterate through child elements of root
		for(Iterator<Element> it = root.elementIterator(); it.hasNext();) {
			Element element = it.next();
			System.out.println(element.getStringValue());
		}
	}
	// 指定迭代特定名称的子节点的信息,这里只student这个标签的名称
	public static void getElementInfoWithName(Document doc) {
		//get root element
		Element root = doc.getRootElement();
		
		// iterate through child elements of root
		for(Iterator<Element> it = root.elementIterator("student"); it.hasNext();) {
			Element element = it.next();
			System.out.println(element.getStringValue());
		}
	}
	
}

运行结果是一样的。

上面都是读取文件和解析些xml内容,下面介绍DOM4J来写内容到xml文件。

我们写的这个student-new.xml,默认生成在根目录下,内容和上面student.xml一样,看看我的代码是如何实现的。

package com.anthony.parse;

import java.io.FileWriter;
import java.io.IOException;

import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;

public class DOM4JWriteTest {

	public static void main(String[] args) throws IOException {
		Document doc = createDocument();
		FileWriter out = new FileWriter("student-new.xml");
		doc.write(out);
		out.close();
	}
	
	public static Document createDocument() {
		Document doc = DocumentHelper.createDocument();
		//add root element
		Element root = doc.addElement("students");
		
		//add student1
		Element student1 = root.addElement("student");
		student1.addElement("age")
				.addText("18");
		student1.addElement("name")
				.addText("ZhangSan");
		student1.addElement("agender")
				.addText("male");
		
		//add student2
		Element student2 = root.addElement("student");
		student2.addElement("age")
				.addText("19");
		student2.addElement("name")
				.addText("LiSi");
		student2.addElement("agender")
				.addText("female");
		return doc;
	}
}

运行结果,刷新项目,根目录下就出现student-new.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<students><student><age>18</age><name>ZhangSan</name><agender>male</agender></student><student><age>19</age><name>LiSi</name><agender>female</agender></student></students>

打开student-new.xml 内容是这样,内容是对,只不过是没有换行,不美观,这个没关系,你可以手动一个标签一个标签去换行试试,效果就是说明按照你想要的格式写入了内容。写入xml的思路就是,先创建一个document对象,然后定义根标签,然后根标签下定义一个标签,名称你自己写一个,然后一层添加标签,添加属性或者添加Text。

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值