DOM解析XML文件

DOM的全称是Document Object Model,也即文档对象模型。在应用程序中,基于DOM的XML分析器将一个XML文档转换成一个对象模型的集合(通常称DOM树),应用程序正是通过对这个对象模型的操作,来实现对XML文档数据的操作。通过DOM接口,应用程序可以在任何时候访问XML文档中的任何一部分数据,因此,这种利用DOM 接口的机制也被称作随机访问机制。

对于XML应用开发来说, DOM就是一个对象化的XML数据接口,一个与语言无关、与平台无关的标准接口规范。它定义了HTLM文档和XML 文档的逻辑结构,给出了一种访间和处理HTML文档和XML 文档的方法。利用DOM, 程序开发人员可以动态地创建文档,遍历文档结构,添加、修改、删除文档内容,改变文档的显示方式等等。

文档代表的是数据,而DOM则代表了如何去处理这些数据。在Java中最常用作配置文件。我们最常做的就是“获取”。

Java中一切皆对象,DOM中一切皆节点。

最常见的节点类型:

  1. 元素节点:元素是XML 的基本构件。元素可以由其它元素、文本节点或两者都有来作为其子节点。元素节点还是可以有属性的唯一类型的节点。
  2. 属性节点:属性节点包含关于元素节点的信息,但实际上,不认为它是元素的子节点
  3. 文本节点:确切来讲,文本节点是文本。它可以包含许多信息或仅仅是空白。(空白部分也算文本节点
  4. 文档(根节点):文档节点是整个文档中所有其它节点的父节点. (根节点不等于根元素节点)

在DOM接口规范中,有四个基本的接口: Document, Node, NodeList 以及NamedNodMap。

  1. Document 接口是对文档进行操作的入口。它是从Node接口继承过来的。
  2. Node接口是其他大多数接口的父类,像Document(文档) Element(元素) Attr(属性) Text(文本) Comment(注释)等接口都是从Node接口继承过来的。
  3. NodeList接口是一个节点的集合,它包含了某个节点中的所有子节点。
  4. NamedNodMap接口也是一个节点的集合,通过该接口,可以建立节点名和节点之间的一映射关系,从而利用节点名可以直接访问特定的节点。

平常我们最常操作的四个对象:

  1. Node对象: DOM 结构中最为基本的对象
  2. Document对象:代表整个XML的文档。(通过它可以获取整个文档的所有内容)
  3. NodeList对象: 包含一 个或者多个Node的列表。
  4. Element对象:代表XML文档中的标签元素。

概念性问题我觉得了解以上这些就可以了,下面用程序来说明。注释已经说的很清楚了。

先来看xml文件结构

<?xml version="1.0" encoding="UTF-8"?>
<mappings>
	<mapping>
		<property name = "haha" age = "17">123</property>
		<property name = "heihei" age = "18"></property>
	</mapping>
	<mapping></mapping>
</mappings>
public class Test {

	public static void main(String[] args) throws Exception {
		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();		//获的文档解析工厂
		DocumentBuilder db = dbf.newDocumentBuilder();														//获取文档解析器
		InputStream is = Test.class.getResourceAsStream("/config.xml");								//加载xml文件资源
		Document doc = db.parse(is);																							//解析获取Document对象
		Element root = doc.getDocumentElement(); //获取根标签元素
		parseElement(root);
	}
	
	//递归遍历文档内所有节点  =====>  Node 可以判断其节点类型					//XML中一切都是节点
	public static void parseElement(Element element) {
		//显示开始标签
		String tagName = element.getTagName();											//利用元素Element对象获取标签名。例如<mappings> --->  mappings
		StringBuffer sb = new StringBuffer("<" + tagName);
		NamedNodeMap attrMap = element.getAttributes();
		for(int index = 0; index < attrMap.getLength(); index++) {
			Attr attr =  (Attr) attrMap.item(index);														//获取属性对象Attr	
			String attrName = attr.getName();															//获取属性名
			String attrValue = attr.getValue();														//获取属性值
			sb.append(" " + attrName + " = \"" + attrValue + "\"");
		}
		System.out.print(sb.append(">").toString());
		
		NodeList nodeList = element.getChildNodes();	//获取该元素节点的所有子节点(包含该元素节点下的所有文本节点,子元素节点,注释节点等)
		for(int index = 0; index < nodeList.getLength(); index++) {
			Node charNode = nodeList.item(index);				
			short nodeType = charNode.getNodeType();					//获取节点类型
			switch (nodeType) {
			case Node.ELEMENT_NODE:					
				parseElement((Element)charNode);//如果是元素(即可能存在子元素),递归判断
				break;
			case Node.TEXT_NODE:			//如果是文本
				System.out.print(charNode.getTextContent());	//获取文本内容
				break;
			case Node.COMMENT_NODE:		//如果是注释
				System.out.print("<!-- " + ((Comment) charNode).getData() + " -->");			//获取注释内容
				break;
			default: 
				break;
			}
		}
		
		//显示结束标签
		System.out.print("</" + tagName +">");
	}
	
}

输出结果:

对该xml文件,就程序的流程:

  1. 输出:<mappings>
  2. 遇到文本节点(即第一行与第二行之间的空白内容)原样输出
  3. 遇到元素节点再次执行方法(进入递归),输出:空白内容 + <property name = "haha" age = "17">123</property>
  4. ......

工具化:

为了方便以后的操作,自制解析工具如下:

public abstract class MecXmlParse {
	private static DocumentBuilder db = null;
	static {
		DocumentBuilderFactory dbf  = DocumentBuilderFactory.newInstance();			//获取文档解析工厂
		try {
			db = dbf.newDocumentBuilder();															//获取文档解析器
		} catch (ParserConfigurationException e) {
			e.printStackTrace();
		}
	}
	
	public MecXmlParse() {}
	
	//拿到Document对象
	public static Document load(String filePath) throws FileNotFoundException {
		InputStream fis = null;
		try {
			fis = MecXmlParse.class.getResourceAsStream(filePath);
			return db.parse(fis);
		} catch (Exception e) {
			throw new FileNotFoundException("[" + filePath + "]");
		}finally {
			if(fis != null) {
				try {
					fis.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
	
	public void parseTag(Document document, String tagName) {
		NodeList nodeList = document.getElementsByTagName(tagName);
		for(int index = 0; index < nodeList.getLength(); index++) {
			Element element = (Element) nodeList.item(index);
			dealElement(element, index);
		}
	}
	
	public Element getRoot(Document document) {
		return document.getDocumentElement();		//获取根节点			
	}
	
	public void parseNode(Element element) {
		NodeList nodeList = element.getChildNodes();
		for(int index = 0; index < nodeList.getLength(); index++) {
			Node node = nodeList.item(index);
			if(node.getNodeType() == Node.ELEMENT_NODE) {
				dealElement((Element)node, index);								//给的工具中只处理元素
			}
		}
	}
	
	public abstract void dealElement(Element element, int index);
	
}

测试:

public class Test02 {

	public static void main(String[] args) {
		MecXmlParse parse  = new MecXmlParse() {
			
			@Override
			public void dealElement(Element element, int index) {
				String tagName = element.getTagName();
				System.out.print("\n<" + tagName +">");
				parseNode(element);
				System.out.print("</" + tagName + ">\n");
			}
		};
		
		try {
			Element root = parse.getRoot(MecXmlParse.load("/config.xml"));
			parse.parseNode(root);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
	}

}

结果:

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值