DOM解析XML文件

在JAVA中XML解析可以使用DOM,SAX,JDOM,JAXB四种方式。

DOM是基于树和节点的文档对象模型(Document Object Module)。DOM编程不要其它的依赖包,因为JDK里自带的JDK里含有的解析所需要用到的org.w3c.dom和javax.xml.parsers等包。DOM不适合于解析较大的XML文件,因为它会将XML全部加载到内存,如果XML文件很大,则会很费内存,而且解析得很慢。这点在使用时应考虑。

本次示例中,我们将解析一个XML文件,并将其数据保存到一个VO对象集合中。

(1)book.xml文件:

<?xml version="1.0" encoding="UTF-8"?>
<persons>
	<person id="0001">
		<name>Smith</name>
		<sex>male</sex>
		<age>20</age>
	</person> 
	<person id="0002">
		<name>Tom</name>
		<sex>male</sex>
		<age>22</age>
	</person> 
	<person id="0003">
	   <name>Tom</name>
	   <sex>female</sex>
	   <age>33</age>
	</person> 
</persons>


(2)建立一个Person.java的VO对象

public class Person {
	private String id;
	private String name;
	private String sex;
	private int age;
	
	//省略了Getter和Setter方法
}


(3)DOM解析XML文件的代码如下:

package review.fileoper;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class DomParseXMLTest {

	/**
	 * DOM解析XML文件
	 * @param file
	 * @return
	 * @throws Exception
	 */
	public List<Person> domParseXML(File file) throws Exception{
		List<Person> personList = new ArrayList<Person>();	//保存解析得到的Person对象
		
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		DocumentBuilder builder = factory.newDocumentBuilder();
		
		Document doc = builder.parse(file);
		// 获得文档的根元素
		Element element = doc.getDocumentElement();
		// 根据节点名来获得所有的person元素
		NodeList personNodes = element.getElementsByTagName("person");
		for (int i = 0; i < personNodes.getLength(); i++) {
			Element personEle = (Element) personNodes.item(i);
			Person p = new Person();
			// 得到节点的属性值
			p.setId(personEle.getAttribute("id"));
			// 得到元素下的所有子节点
			NodeList personMeta = personEle.getChildNodes();
//			System.out.println("personMeta.getLength() = " + personMeta.getLength());
			for (int j = 0; j < personMeta.getLength(); j++) {
				Node meta = personMeta.item(j);
				if("name".equals(meta.getNodeName())){
					p.setName(meta.getTextContent());
				}else if("sex".equals(meta.getNodeName())){
					p.setSex(meta.getTextContent());
				}else if("age".equals(meta.getNodeName())){
					p.setAge(Integer.parseInt(meta.getTextContent()));
				}
			}
			personList.add(p);
		}
		return personList;
	}
	
	/**
	 * 打印解析得到的结果personList
	 * @param personList
	 */
	public void printPerson(List<Person> personList){
		System.out.println("----------printPerson------------");
		for(Person per : personList){
			System.out.println("id:" + per.getId() + ",name : " + per.getName()
					+ "\nsex : " + per.getSex() + ",age: " + per.getAge());
		}
	}
	
	public static void main(String[] args) throws Exception {
		DomParseXMLTest test = new DomParseXMLTest();
		//获得工程的根目录
		String root = DomParseXMLTest.class.getResource("/").getPath();
//		InputStream is = DomParseXMLTest.class.getClassLoader().getResourceAsStream("person.xml");
		
		File file = new File(root + "/review/fileoper/person.xml");
		List<Person> personList = test.domParseXML(file);
		test.printPerson(personList);
	}
}


运行结果如下:

 

DOM解析的过程中,我们需要注意以下几点:

(1)获得元素子节点的问题

代码中personMeta.getLength()的结果为7,这可能让多数初学者困惑不已,XML文件中person节点下明明只有三个子节点,怎么会变成7个了呢,我们可以调试程序发现了下面的结果:

事实上XML文件中各节点之间都存在换行符“\n\t”或者“\n\t\t”等,DOM解析时也会把它当成是一个子节点(文本节点)所以就会比我们预期的要多,person节点的子节点分布如下图,其中1、3、5、7都是换行符。文本节点的类型是“#text”,值为“[\n[\t]*]+”。大家也可以试下,把上面的XML文件中的内容写在一行,这样解析的结果就变成我们预期的3个子节点了

(2)谈下Node 和Element的区别

Node(节点)是DOM层次结构中的任何类型的对象的通用名称,Node有很多类型,如元素节点,属性节点,文本节点,注释节点等,通过NodeType区分,常见的有:

 

枚举值

对应类型

ELEMENT_NODE

Element节点

ATTRIBUTE_NODE

Attr节点

TEXT_NODE

文本节点

COMMENT_NODE

Comment节点

DOCUMENT_NODE

Document节点

DOCUMENT_TYPE_NODE

DocumentType节点

NOTATION_NODE

注释节点

而Element是继承自Node接口,范围比Node要小,必须是含有完整信息的节点才是一个元素,一个节点不一定是一个元素,但元素一定是一个结点

node只是具有了一些通用的方法,而element则具有更具体的功能,尤其是对节点的属性值操作更加方便,具体可以查看API文档。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值