Java代码实现DOM解析XML

DOM概述

  • DOM全称为Document Object
    Model
    ,中文名为文档对象模型,是W3C组织推荐的处理可扩展置标语言的标准编程接口。它是一种与平台和语言无关的应用程序接口(API),它可以动态地访问程序和脚本,更新其内容、结构和www文档的风格。
  • DOM是把整个XML文件看成是一个倒挂的树形结构来解析,其中使用的包是org.w3c.dom。

XML文件

现在有一个文件名为department.xml的XML文件,文件所在位置为Java文件所在的文件夹下,文件内容如下:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<department>
	<student>
		<name id="100">阿伟</name>
		<age>20</age>
	</student>
	<student>
		<name>杰哥</name>
		<age>40</age>
	</student>
	<student>
		<name>彬彬</name>
		<age>20</age>
	</student>
</department>

在XML文件中,一切皆为节点

使用DOM获取一个节点的名称和值

在解析XML文件时,需要获取节点的值和名称。首先要先获取根节点,然后才能对根节点进行操作来获取子节点的名称或值。获取根节点需要通过四个步骤:

  1. 获取DocumentBuilderFactory解析工厂对象
  2. 通过DocumentBuilder解析工厂对象,获取解析对象
  3. 通过文档解析器Document获取文档对象
  4. 获取根节点root
//单例模式,获取document解析工厂对象
	DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
	
//通过文档解析工厂对象,获取解析对象
	DocumentBuilder builder = factory.newDocumentBuilder();
	
//通过文档解析器获取文档对象
	Document doc = builder.parse("department.xml");
		
//获取根节点
	Element root = doc.getDocumentElement();

获取到根节点之后,需要通过几个常用方法来获取XML中节点的名称或值:

  • getFirstChild():获取此节点的第一个子节点
  • getNextSibling():获取此节点的下一个兄弟节点
  • getTextContent():获取此节点的文本内容

然后先来看看XML文件的构造:
在这里插入图片描述
假如想获取student下面的name中的值,一般情况下只需要获取到student节点,它的第一个子节点即是我们要找的值,用上述函数表示就是:
root.getFirstChild().getFirstChild().getTextContent()
但是实际运行起来,却根本无法找到name里的内容。
原因是:在XML里,一切皆为节点

因为要保证XML文件代码的可读性和美观,人们编写XML文件时喜欢进行换行,平时看不见的换行符在XML里也作为节点被看待,所以在department.xml文件中,student节点存在一个兄弟节点,也就是看不见的换行。所以要找到name节点的节点名称和name的值时,用上述函数正确表示为:

//万物皆为节点
//获取节点名称"name"并输出
	System.out.println(root.getFirstChild().getNextSibling().getFirstChild().getNextSibling().getNodeName());
//获取"name"的值"阿伟"并输出
	System.out.println(root.getFirstChild().getNextSibling().getFirstChild().getNextSibling().getTextContent());

编写工具类解析XML的所有节点

上述是使用DOM解析XML的基本操作。因为“一切皆为节点”的缘故,解析过程繁琐且不灵活。为了解析更为方便,我们可以编写一个工具类来方便解析。其中用到了NameNodeMap接口和方法:

  • NameNodeMap接口:表示可以通过名称访问的节点的集合
  • item():返回NameNodeMap集合中第 index 个项
  • getLength():获取NameNodeMap集合的长度

封装获取文档对象代码

public static Document getDocumentObject(String xmlName) throws ParserConfigurationException, SAXException, IOException {
		//单例模式,获取document解析工厂对象
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		//通过文档解析工厂对象,获取解析对象
		DocumentBuilder builder = factory.newDocumentBuilder();
		//通过文档解析器获取文档对象
		Document doc = builder.parse(xmlName);
		return doc;
	}

定义visit()方法用于解析

	public static void visit(Node start) {
		System.out.println(start.getNodeName()+"···"+start.getNodeValue());
		//确保传递的节点对象是Element
		//因为Attriubte一定是在Element中
		if(start.getNodeType() == Node.ELEMENT_NODE) {
			NamedNodeMap nnm = start.getAttributes();
			//处理属性节点对象
			for(int i = 0;i < nnm.getLength();i++) {
				//通过NameNodeMap获取节点索引,便于循环操作
				Node attr = nnm.item(i);
				System.out.println(attr.getNodeName()+"···"+attr.getNodeValue());
			}
			for(Node sub = start.getFirstChild();sub != null;sub = sub.getNextSibling()) {
				visit(sub);
			}
		}
	}

工具类完整代码

public class DOMTool {
	
	public static Document getDocumentObject(String xmlName) throws ParserConfigurationException, SAXException, IOException {
		//单例模式,获取document解析工厂对象
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		//通过文档解析工厂对象,获取解析对象
		DocumentBuilder builder = factory.newDocumentBuilder();
		//通过文档解析器获取文档对象
		Document doc = builder.parse(xmlName);
		return doc;
	}
	
	public static void visit(Node start) {
		System.out.println(start.getNodeName()+"···"+start.getNodeValue());
		//确保传递的节点对象是Element
		//因为Attriubte一定是在Element中
		if(start.getNodeType() == Node.ELEMENT_NODE) {
			NamedNodeMap nnm = start.getAttributes();
			//处理属性节点对象
			for(int i = 0;i < nnm.getLength();i++) {
				//通过NameNodeMap获取节点索引,便于循环操作
				Node attr = nnm.item(i);
				System.out.println(attr.getNodeName()+"···"+attr.getNodeValue());
			}
			for(Node sub = start.getFirstChild();sub != null;sub = sub.getNextSibling()) {
				visit(sub);
			}
		}
	}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值