使用Java解析XML操作DOM

@author:Edison丶梦楠

转载请注明作者~!

 

关于什么是DOM,请自行查阅!作者在这里不做解释。

本文演示的XML为了演示方便,放在项目中,采用绝对路径的方法。

以下是创建的XML:

 

 

获得Document对象模型的方法:

1:找到DocumentBuilderFactory工厂类,调用newInstance();方法返回的是工厂类对象。factory

2:通过factory对象调用newDocumentBuilder()方法,返回DocumentBuilder对象builder

3:(返回Document的第一种方式)通过builder对象调用newIDocument()方法,返回Document对象。注意:此方法是针对没有XML文档时调用的方法。(调用此方法,会在内存中建立一个树状Document模型

返回Document对象的第二种方式:通过builder对象调用parse(File  f这里是XML的文件路径,也可以接收一个输入流) 也可以返回Document对象,但是这个方法是建立在有XML文件的前提下的。

PS:解析XML文档时,返回的是Document对象,和DateFormat中的parse()方法返回的是Date对象的理解相同。

为了更好的解释,博主采用画图的方式进行进一步理解。

 

下面是具体实现

在项目中引入Junit4单元测试插件,

创建test方法

 

DOM操作1:获取元素内容

package com.hard.dom;
import java.io.File;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.junit.Assert;
import org.junit.Test;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

public class DOMTest {
	private File  f = new File("E:/java_project/DOM/user.xml");
	@Test
	public void testSelect() throws Exception {
		//获取Document文档对象
		DocumentBuilderFactory  dbf =  DocumentBuilderFactory.newInstance();
		DocumentBuilder db =  dbf.newDocumentBuilder();
		Document d = db.parse(f);
		//获取文档对象中的根节点
		Element root = d.getDocumentElement();
		/*
		 * 获取根节点下的所有子元素。因为我们知道想要获取
		 * 哪一个根节点下的子元素,所以我们调用item(index)
		 * index表示找linkman下的第几个子元素
		 * 因为返回的是NodeList集合,所以我们必须强转为Element。
		 * 得到子元素 
		 */
		Element linkmanChild = (Element) root.getElementsByTagName("linkman").item(0);
		//获取linkman元素下的子元素name元素
		Element name = (Element) linkmanChild.getElementsByTagName("name").item(0);
		//使用断言,看看结果能不能达到我们的预想
		Assert.assertEquals("错误提示~!", "博主很年轻",name.getTextContent());
		System.out.println(name.getTextContent());
	}
}

 

断言显示蓝条,并没有报错。

 

打印结果:

 

 

DOM操作2:修改XML操作:

	@Test
	public void testAlter() throws Exception {
		//获得Document文档对象
		Document  doc = 	DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(f);
		//获得根节点
		Element root = doc.getDocumentElement();
		//获得根节点下的子元素
		Element linkman =(Element)  root.getElementsByTagName("linkman").item(1);
		//获得linkman元素下的子元素
		Element name =(Element) linkman.getElementsByTagName("addr").item(0);
	  //修改name属性文本中的新内容
		name.setTextContent("安徽省");
	//使用断言 查看是否成功修改
	 Assert.assertEquals("you is false!", "安徽省",name.getTextContent());
	}

 

 

此时修改成功只是修改了内存中的Document对象模型,而实际文件内容并没有发生改变。

此时我们就需要做同步操作。核心类:TransFormer

 

	 //同步操作 把内存中的文档模型同步到本地磁盘中
	TransformerFactory factory =  TransformerFactory.newInstance();
	Transformer transformer = factory.newTransformer();
	//xmlSource 表示源文件   outputTarget 表示目标文件,要同步到哪个文件
	Source xmlSource = new DOMSource(doc);
	Result  target = new  StreamResult(f);
	transformer.transform(xmlSource, target);

Source为接口,所以必须new它的实现类。通过实现类的构造器传入源文件。

Result也为接口。所以必须new它的实现类,但注意:这里我们不能再调用DOMResult对象,因为内存中的数据想要同步到本地磁盘中,就必须以(Stream)流的方式,所以此时我们得new它的实现类StremResult(目标文件);

 

此时我们查看user.xml中,博主的addr已被改变。

 

 

DOM操作3:添加一个新的用户信息(向本地磁盘XML文件中添加一个新的人员信息)

@Test  //向本地磁盘XML文件中添加一个新的人员信息
	public void testAdd() throws Exception {
		//获取Document文档对象
	Document doc =  	DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(f);
		//获取根节点
   Element root = doc.getDocumentElement();
      //创建新的子节点元素
    Element linkman =  doc.createElement("linkman");
	 Element name=  doc.createElement("name");
	 name.setTextContent("陈二蒙");
	 Element age = doc.createElement("age");
	 age.setTextContent("21");
	 Element addr = doc.createElement("addr");
	 addr.setTextContent("安徽省六安市");
	 /*
	  * 此时我们在内存模型中创建了
	  * <linkman></linkman>
	  * <name></name>
	  * <age></age>
	  * <addr></addr>
	  * 并为他们设置了元素的文本内容
	  * 但是我们发现,他们并没有包含在linkman父元素中(同级关系)
	  * 所以此时我们得把name,age,addr设为linkman的子元素 
	  */
	 root.appendChild(linkman);
	 linkman.appendChild(name);
	 linkman.appendChild(age);
	 linkman.appendChild(addr);
	 //把内存中的树状结构模型同步到本地磁盘中
	 TransformerFactory.newInstance().newTransformer().transform(new DOMSource(doc),new StreamResult(f) );
	}

此时我们再回到user.xml文件中可以看到内容已经发生改变

 

 

DOM操作4:设置和获取元素属性

//设置和获取元素的属性
	@Test
	public void testProperty() throws Exception {
		/*
		 * 给linkman元素添加一个id属性
		 */
		//获取Document文档对象.
		Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(f);
		//获取根节点
		Element  root =  doc.getDocumentElement();
		//获取根节点子元素
    	Element linkmanEl = (Element)	root.getElementsByTagName("linkman").item(2);
		//给根节点设置属性
		linkmanEl.setAttribute("id", "2");
	  //将模型写入本地xml文件
		TransformerFactory.newInstance().newTransformer().transform(new DOMSource(doc), new StreamResult(f));
		/*
		 * 获取linkman的属性
		 */
		linkmanEl.getAttribute("id");
		//断言测试是否成功获取
		Assert.assertEquals("2", linkmanEl.getAttribute("id"));
        //显示绿条,表示成功获取
		
	}

此时我们看到,第三个linkman元素被添加了一个id的属性

 

DOM操作5:删除指定用户

	@Test    //删除第一个用户的信息
	public void testDelete() throws Exception {
	   //获取文档对象
		Document doc = 	DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(f);
		//获取根节点
		Element root = doc.getDocumentElement();
		//获取第一个item(0) 的linkman元素
		Element linkmanEl =(Element) root.getElementsByTagName("linkman").item(0);
		//通过根节点的removeChild方法,移除此指定的linkman元素
		root.removeChild(linkmanEl);
		///同步到本地xml磁盘文件中
		TransformerFactory.newInstance().newTransformer().transform(new DOMSource(doc), new StreamResult(f));

此时我们发现第一个元素已被删除

 

DOM操作6:创建Document对象

创建Document对象有两种方式,前文提到过。

在我们创建Document对象时,有两种情况:

第一种是xml文件存在的情况下,我们解析过后,直接返回Document文档对象,并不需要再创建根目录。

第二种是xml文件不存在的情况下,调用Document对象的.newDocument()方法,创建文档对象,并创建根目录。

我们考虑的上述第二种情况是属于极端情况,在实际业务中可能不存在。实际业务中,一般不会存在没有xml的情况。

一般的,即使xml文件没有内容,也会有根节点。

 

@Test  //创建Document对象
	public void testCreateDocument() throws Exception {
	    //创建builder对象  先不要解析 因为我们不知道文件存不存在
		DocumentBuilder builder=	DocumentBuilderFactory.newInstance().newDocumentBuilder();
		Document  doc = null;
		Element root = null;
		if(f.exists()) {
			//如果文件存在,则解析该文件
			builder.parse(f);
		}else {
			//如果不存在,则新建文档对象
			doc = builder.newDocument();
			//并为该对象创建根元素
		 root=doc.createElement("contacts");
		  //并把该根元素追加作为文档对象的子元素
		 doc.appendChild(root);
		}
		
		/**
		 * 下面测试保存一个联系人
		 */
	//创建子元素
	Element linkmanEl = 	doc.createElement("linkman");
	linkmanEl.setAttribute("sex", "男");
	Element nameEl=  doc.createElement("name");
	Element ageEl = doc.createElement("age");
	Element addrEl= doc.createElement("addr");
	//为name,age,addr添加文本内容
	nameEl.setTextContent("彭于晏");
	ageEl.setTextContent("35");
	addrEl.setTextContent("江苏南京");
	//把linkman作为子元素追加到父元素contacts中
	root.appendChild(linkmanEl);
	//把name,age,addr作为子元素追加到父元素linkman中
	linkmanEl.appendChild(nameEl);
   linkmanEl.appendChild(ageEl);
   linkmanEl.appendChild(addrEl);

   //同步到本地磁盘文件中
   TransformerFactory.newInstance().newTransformer().transform(new DOMSource(doc), new StreamResult(f));
	}

此时,我们把项目中的xml文件删除,看看能否成功创建文件,并添加一个用户信息。

 

 

成功啦!

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值