XML@TOC
#我们一起学习XML文件解析
XML文件是java编程中的常客,用来它存储数据非常的方便,而我们通常要做的就是解析XML文件里面的存储的内容。当我们编写过一些XML文件的解析代码之后,就会感觉到文件的解析存在着许多相似的代码,那我们能不能把这些相似的代码提取出来,编写成相关XML解析的工具,这样极大地方便了以后对XML文件的解析,也符合java面向工具的编程思想,一下就是我写的xml相关的解析工具。
下面为需要解析的XML文件
<?xml version="1.0" encoding="UTF-8"?>
<students>
<student id="03171111" name="华茜茜" major="通信工程">
<hoppies>
<hoppy> 书法</hoppy>
<hoppy> 看书</hoppy>
<hoppy> 画画</hoppy>
</hoppies>
</student>
<student id="03172222" name="鸽子" major="通信工程">
<hoppies>
<hoppy> 跳舞</hoppy>
<hoppy> 游泳</hoppy>
<hoppy> 发呆</hoppy>
</hoppies>
</student>
<student id="031723333" name="孟瘦瘦" major="计算机">
<hoppies>
<hoppy> 跳舞</hoppy>
<hoppy> 游泳</hoppy>
</hoppies>
</student>
</students>
下面是解析XML文件的普通做法
package com.mec.xml;
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 XMLpratise {
public static void main(String[]args){
try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
InputStream is = Class.class.getResourceAsStream("/students.xml");
Document document = db.parse(is);
NodeList studentList = document.getElementsByTagName("student");
for(int index=0; index < studentList.getLength(); index++){
Element student = (Element)studentList.item(index);
String id = student.getAttribute("id");
String name = student.getAttribute("name");
String major = student.getAttribute("major");
StringBuffer sBuffer = new StringBuffer().
append("学号 :" + id + " ").
append("姓名:" + name + " ").
append("专业:" + major + " ");
System.out.println(sBuffer);
NodeList hoppies = student.getElementsByTagName("hoppy");
for(int i = 0; i < hoppies.getLength(); i++){
Element hoppyTag = (Element)hoppies.item(i);
String hoppy = hoppyTag.getTextContent();
System.out.println("\t" + hoppy);
}
}
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e){
e.printStackTrace();
}
}
}
输出的结果如下:
仔细观察以上的代码我们可以发现
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
InputStream is = Class.class.getResourceAsStream("/students.xml");
Document document = db.parse(is);
这几行代码似乎就是一种固定的套路,解析不同的文件只需要更改文件的绝对路径即可,特别是对于前两行,其实就是生成了一个DocumentBuilder类的对象,但不管是解析那种类型的XML文件都只需要生成一个该类的对象,因此我们可以把它写成
静态块。
static {
try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
} catch (ParserConfigurationException e) {
e.printStackTrace();
}
}
我们继续观察下面的代码:
NodeList studentList = document.getElementsByTagName("student");
for(int index=0; index < studentList.getLength(); index++){
Element student = (Element)studentList.item(index);
//对student标签的解析... ...
NodeList hoppies = student.getElementsByTagName("hoppy");
for(int i = 0; i < hoppies.getLength(); i++){
Element hoppyTag = (Element)hoppies.item(i);
//对hoppy标签的解析... ...
}
}
以上代码的两个注释部分应该是由使用者根据XML的写法具体实现的,作为xml文件解析工具的开发者是不知道 未来工具使用者要怎么具体处理文件中的相关内容的。因此我们的工具应该是一个抽象类。
根据上面的解析方式,我们可以看到,XML文件中存在两种解析方式:
1、知道文件和标签进行解析,例如 获取document中的student标签
2、知道外标签和标签进行解析,例如 获取student下的hoppy标签
综上所述,我们应该准备两种方法来解析文件:
public void parseTag(Document document, String tagName){
NodeList nodeList = document.getElementsByTagName(tagName);
for(int index = 0; index < nodeList.getLength(); index++){
Element ele = (Element)nodeList.item(index);
praseXml(ele, index);
//该函数就是工具使用者需要完成的具体解析过程
}
}
public void parseTag(Element element, String tagName){
NodeList nodeList = element.getElementsByTagName(tagName);
for(int index = 0; index < nodeList.getLength(); index++){
Element ele = (Element)nodeList.item(index);
praseXml(ele, index);
}
}
XML 解析工具代码如下:
package com.mec.xml;
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 XMLTool {
private static DocumentBuilder db;
static {
try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
db = dbf.newDocumentBuilder();
} catch (ParserConfigurationException e) {
e.printStackTrace();
}
}
public abstract void praseXml(Element ele, int index);
public static Document loadXml(String fileName) throws SAXException, IOException{
InputStream is = Class.class.getResourceAsStream(fileName);
Document document = null;
document = db.parse(is);
return document;
}
public void parseTag(Document document, String tagName){
NodeList nodeList = document.getElementsByTagName(tagName);
for(int index = 0; index < nodeList.getLength(); index++){
Element ele = (Element)nodeList.item(index);
praseXml(ele, index);
}
}
public void parseTag(Element element, String tagName){
NodeList nodeList = element.getElementsByTagName(tagName);
for(int index = 0; index < nodeList.getLength(); index++){
Element ele = (Element)nodeList.item(index);
praseXml(ele, index);
}
}
}
工具使用方法
public class Text {
public static void main(String[] args) throws SAXException, IOException {
new XMLTool() {
@Override
public void praseXml(Element ele, int index) {
String id = ele.getAttribute("id");
String name = ele.getAttribute("name");
String major = ele.getAttribute("major");
StringBuffer sBuffer = new StringBuffer().
append("学号 :" + id + " ").
append("姓名:" + name + " ").
append("专业:" + major + " ");
System.out.println(sBuffer);
new XMLTool() {
@Override
public void praseXml(Element ele, int index) {
String hoppy = ele.getTextContent();
System.out.println("\t" + hoppy);
}
}.parseTag(ele, "hoppy");
}
}.parseTag(XMLTool.loadXml("/students.xml"), "student");
//其实这里直接new了一个对象,然后直接调用了ParaseTag方法
}
}
结果如下:
总结
把XML文件的解析写成工具,用到了“动”和“静”结合的思想,“动“是指抽象方法的实现是需要工具使用者在使用时完成编写的:
public abstract void praseXml(Element ele, int index);
“静”则是工具编写中固定的成分:
public void parseTag(Document document, String tagName);
public void parseTag(Element element, String tagName);
工具编写完全可以有一劳永逸的效果,以后的XML文件解析就在也不用愁了哈~~~
今天就到这里,下次给大家分享下properties文件的解析哟~