【java】XML文件解析工具--程序设计思想

本文探讨了工具化程序设计思想,以XML文件解析为例,展示如何通过创建工具类实现代码复用。文章介绍了XML文档的解析方法,包括直接解析、使用工具和通过解析器处理,并强调了面向对象编程中静态和动态代码的结合。作者认为理解和应用工具化思想对于高级程序设计至关重要。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

工具化程序设计思想–XML文件解析工具

XML解析

对于讲述 xml 文件解析的基本方法不是本文的重点,本文旨在阐述“工具化程序设计思想”,即,通过工具化 xml 解析方法,以达到代码复用的目的。

XML文档示例

<?xml version="1.0" encoding="UTF-8"?>
<students>
	<student id="03191001" name="张三" sex="男">
		<hobby>爬山</hobby>
		<hobby>游泳</hobby>
	</student>
	<student id="03191002" name="丽丽" sex="女">
		<hobby>跳舞</hobby>
		<hobby>唱歌</hobby>
	</student>
</students>

直接解析XML文件

package com.mec.xml_parser.test;

import java.io.IOException;
import java.io.InputStream;

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

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

public class TestForXmlParser {
	private static DocumentBuilder db;
	static {
		try {
			db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
		} catch (ParserConfigurationException e) {
			e.printStackTrace();
		}
	}
	public static void main(String[] args) {
		try {
			InputStream is = Class.class.getResourceAsStream("/student.xml");
			Document doc = db.parse(is);
			
			NodeList studentList = doc.getElementsByTagName("student");
			for (int i = 0; i < studentList.getLength(); i++) {
				Element student = (Element) studentList.item(i);
				String id = student.getAttribute("id");
				String name = student.getAttribute("name");
				String sex = student.getAttribute("sex");
				System.out.println(id + ", " + name + ", " + sex);
				
				NodeList hobbies = student.getElementsByTagName("hobby");
				for (int j = 0; j < hobbies.getLength(); j++) {
					Element hobby = (Element) hobbies.item(j);
					String hobbyName = hobby.getTextContent();
					System.out.println("\t" + hobbyName);
				}
			}
		} catch (SAXException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
				
	}

}

使用工具解析XML文件

package com.util;

import java.io.IOException;
import java.io.InputStream;

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

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

public abstract class XMLParser {
	private static DocumentBuilder db;
	
	/*
	 * 因为静态块只被调用一次,因此,DocumentBuilder 对象
	 * 只产生一个,这里采用了单例模式
	 */
	static {
		try {
			db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
		} catch (ParserConfigurationException e) {
			e.printStackTrace();
		}
	}
	
	public XMLParser() {
	}

	/*
	 * 这里的异常不必处理,直接抛出即可
	 */
	public static Document loadXml(String xmlPath) throws SAXException, IOException {
		InputStream is = XMLParser.class.getResourceAsStream(xmlPath);
		
		return loadXml(is);
	}
	
	public static Document loadXml(InputStream is) throws SAXException, IOException {
		return db.parse(is);
	}
	
	// 由用户决定的抽象方法,对于处理不同的 xml 文件,有不同的解析方法
	public abstract void dealElement(Element element, int index);
	
	public void parse(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);
		}
	}
	
	/*
	 * 要取得标签里的内容,就需要调用 getElementsByTagName() 方法
	 * 来返回一个 NodeList 对象,但引用这个方法的对象的类型却不同,可能
	 * 存在 Document 和 Element 两种类型,因此需要重载 parse() 方法
	 */
	public void parse(Element element, String tagname) {
		NodeList nodeList = element.getElementsByTagName(tagname);
		for (int index = 0; index < nodeList.getLength(); index++) {
			Element ele = (Element) nodeList.item(index);
			dealElement(ele, index);
		}
	}
	
}

通过解析器处理XML文件

package com.xml_parser;

import java.io.IOException;

import org.w3c.dom.Element;
import org.xml.sax.SAXException;

import com.util.XMLParser;

public class Demo {

	public static void main(String[] args) {
		try {
			new XMLParser() {
				@Override
				public void dealElement(Element element, int index) {
					String id = element.getAttribute("id");
					String name = element.getAttribute("name");
					String sex = element.getAttribute("sex");
					System.out.println(id + ", " + name + ", " + sex);
					
					new XMLParser() {
						@Override
						public void dealElement(Element element, int index) {
							String hobby = element.getTextContent();
							System.out.println("\t" + hobby);
						}
					}.parse(element, "hobby");;
				}
			}.parse(XMLParser.loadXml("/student.xml"), "student");
		} catch (SAXException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		};
	}

}

解析结果

03191001, 张三, 男
	爬山
	游泳
03191002, 丽丽, 女
	跳舞
	唱歌

对于工具化编程的感悟

面向对象程序设计思想的重点就是“工具化”编程思想。解析 xml 文件的操作在程序设计时非常常见,如果每一次进行 xml 解析都采用直接解析的方式,那无疑每次都要编写很多雷同的代码,那将大大降低工作的效率。

	public void parse(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 void parse(Element element, String tagname) {
		NodeList nodeList = element.getElementsByTagName(tagname);
		for (int index = 0; index < nodeList.getLength(); index++) {
			Element ele = (Element) nodeList.item(index);
			dealElement(ele, index);
		}
	}

上述代码是 xml 文档解析工具的核心,实质就是“静”与“动”的结合。通过对象获取节点列表,并对得到的节点进行处理;获取节点列表是固定不变的套路,即,“静”的部分;而对于文件中数据具体的操作是工具无法知道的,工具也无权决定用户对其标签的属性和内容的具体处理过程,这些需要用户决定的操作便是“动”的部分,可以采用抽象方法来处理这个问题。

虽然此XML解析工具并不能处理更复杂的 xml 解析要求,但也算是一个具有相当普适性和实用性的工具类。本文的重点是阐述“工具化程序设计思想”,强调面向对象编程思想的终极目标是代码复用,所以将解析 xml 的方法抽象成一个工具,以领悟其中的思想才是关键。

从XML解析工具可以得出,程序设计应将“工具化”思想和代码复用思想深入骨髓,否则很难在高级程序设计上有所作为。

作者首次发表博文,若有错误或思想所不及之处,还望指正!谢谢阅读!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值