工具化程序设计思想–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解析工具可以得出,程序设计应将“工具化”思想和代码复用思想深入骨髓,否则很难在高级程序设计上有所作为。
作者首次发表博文,若有错误或思想所不及之处,还望指正!谢谢阅读!
本文探讨了工具化程序设计思想,以XML文件解析为例,展示如何通过创建工具类实现代码复用。文章介绍了XML文档的解析方法,包括直接解析、使用工具和通过解析器处理,并强调了面向对象编程中静态和动态代码的结合。作者认为理解和应用工具化思想对于高级程序设计至关重要。

被折叠的 条评论
为什么被折叠?



