欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

DOM解析XML文件

程序员文章站 2022-05-29 08:21:05
...

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 +">");
	}
	
}

输出结果:

DOM解析XML文件

对该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();
		}
	}

}

结果:

DOM解析XML文件

相关标签: java基础