零碎笔记02-关于xml类型文件的解析整理
1.xml文档
1.1 什么是xml文档
MDN的解释:
XML(Extensible Markup Language)是一种类似于 HTML,但是没有使用预定义标记的语言。因此,可以根据自己的设计需求定义专属的标记。这是一种强大将数据存储在一个可以存储、搜索和共享的格式中的方法。最重要的是,因为 XML 的基本格式是标准化的,如果你在本地或互联网上跨系统或平台共享或传输 XML,由于标准化的 XML 语法,接收者仍然可以解析数据。
菜鸟教程的解释:
XML 指可扩展标记语言(eXtensible Markup Language)。XML 被设计用来传输和存储数据,不用于表现和展示数据,HTML 则用来表现数据。XML 很重要,也很容易学习。
简单来说,xml就是一个类似与HTML的语言,它本身没有像HTML一样存在预设的标签标记,我们可以在里面自由定义类似<test></test>的标记,由这种自定义标记组成的文档,就是xml文档,它可以传输和存储数据,也正因如此,一般这种文档也是需要具有相应结构规范的。信息不宜太过杂乱,否则解析就会变得很麻烦。
上面说xml本身是没有预设标签标记的,但有时我们需要在项目的内置的xml进行一些标记的添加,自定义标记就会报错,因为它遵循了某个规范,来保证项目可以正常运行,自定义标记是无法被该规范解析,就会报错。具体为何下面讲解xml解析之后就可以理解了。
1.2 xml的节点
在1.1里我们知道xml文档可以用于数据的传输和存储,我们如何得到数据呢?这时候我们就需要了解节点了。和HTML一样,当我们想在js中获取某个元素的值的时候我们就需要通过document.getElementBy…()类似的方法来获取该元素,然后再去得到该元素的某个值,这个元素就是一个节点。在xml中也是一样的,我们想要得到值就要获取该节点。我们在xml里定义的 <test></test> 标记就是节点。
2.解析xml
2.1 工具
我们解析xml文件需要使用到 dom4j 的jar包,这个我们可以去官网下载,地址在这里:dom4j
2.2 解析过程
2.2.1 文件路径
在java中我们要解析xml,首先需要得到文件路径,在这里就需要使用到File类。
File file = new File("D://xmljson//citys.xml");
2.2.2 解析器
要解析xml文件,我们要使用刚刚导入的 dom4j的jar包里的解析器
// 创建DOM4J解析器
SAXReader sax = new SAXReader();
2.2.3 文件解析
在这里我使用的例子是省市县信息的xml文件,以下是文件的大体结构
红色箭头是节点<mapping>的子节点,蓝色箭头是红色箭头指向的<countries>的子节点,绿色就是蓝色箭头指向的<regions>的子节点。
结构我们分析完了,我们来看怎么获取节点。
我们先要获取文档,就要通过刚刚创建的解析器sax读取文件,然后使用document来接收此文件。接着我们通过document.getRootElement()来获取此文件的根节点,再然后我们想获取根节点的子节点,就通过elements()方法来获取。
代码如下:
Document document = null;
try {
document = sax.read(file); // 读取文件
} catch (DocumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Element root = document.getRootElement();// 获取文件的根节点
List<Element> list = root.elements();// 获取根节点的子节点
运行结果:
从结果可以看出:<mapping>是根节点,<countries>是根节点的子节点,虽然使用了集合list接收,但其实在此文件中<mapping>节点下只有一个<countries>子节点。不过,由此我们应该能反应过来了,我们用集合接收子节点,说明我们要得到这些子节点的话就需要使用循环了。
所以紧接着我们遍历list:
for (int j = 0; j < list.size(); j++) {
if (list.get(j).getName().equals("countries")) { // 判断节点是否为国家
List<Element> regionList = list.get(j).elements(); // 此国家节点信息集合,因为此次则更注重于省份,我命名为了regionlist
for (int k = 0; k < regionList.size(); k++) { // 遍历此国家节点
ps:我虽然命名为regionList,但是其中不是只包含了region的信息,只是因为我此次更侧重于这方面的信息,所以这样子取名,个人习惯,无需在意
list.get(j)就是遍历的子节点,我们通过getName方法来获取节点的名字。所以上面的操作就是判断节点名称是否为countries,如果是true则再创建一个regionList接收countries下的所有子节点。
然后我们再判断子节点里的节点是否为省级节点,再遍历。之后都如此类推。
记住,在省级节点里,除了需要遍历市级节点,我们还需要将省id,省code,省name都作为省对象封装起来,准备随着后续跟着循环被添加进数据库。包括之后的市级信息,区县级信息都是如此。
if (regionList.get(k).getName().equals("regions")) { // 判断节点是否为省级节点
List<Element> info = regionList.get(k).elements(); // 省级节点的子节点集合
List<Province> list2 = new ArrayList<Province>(); // 创建集合接收省份信息
for (int m = 0; m < info.size(); m++) { // 遍历省级节点的子节点
if (info.get(m).getName().equals("id")) { // 判断是否为省节点id
// System.out.println(info.get(m).getText());
pro_id = Integer.valueOf(info.get(m).getText());
}
// System.out.println("===========1==========");
if (info.get(m).getName().equals("code")) { // 判断是否为省节点code
// System.out.println(info.get(m).getText());
pro_code = info.get(m).getText();
}
整个xml文件的解析逻辑就是这样。
下面贴下我的完整代码:
package com.it.parsemain;
import java.io.File;
import java.sql.SQLException;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import com.it.dao.InsertCityDao;
import com.it.dao.InsertDistrictDao;
import com.it.dao.InsertProvinceDao;
import com.it.pojo.City;
import com.it.pojo.District;
import com.it.pojo.Province;
public class XmlParseMain {
public static void main(String[] args) {
File file = new File("D://xmljson//citys.xml");
// 创建DOM4J解析器
SAXReader sax = new SAXReader();
try {
Document document = sax.read(file);
Element root = document.getRootElement();
List<Element> list1 = root.elements();
// 省信息
Integer pro_id = null;
String pro_code = null;
String pro_name = null;
// 市信息
String city_id = null;
String city_name = null;
// 地区信息
String d_id = null;
String d_name = null;
for (int j = 0; j < list1.size(); j++) {
if (list1.get(j).getName().equals("countries")) { // 判断节点是否为国家
List<Element> regionList = list1.get(j).elements(); // 此国家节点信息集合,因为此次则更注重于省份,我命名为了regionlist
for (int k = 0; k < regionList.size(); k++) { // 遍历此国家节点
// System.out.println(regionList.get(k).getName());
if (regionList.get(k).getName().equals("regions")) { // 判断节点是否为省级节点
List<Element> info = regionList.get(k).elements(); // 省级节点的子节点集合
Queue<Province> list2 = new LinkedList<Province>(); // 创建集合接收省份信息
for (int m = 0; m < info.size(); m++) { // 遍历省级节点的子节点
if (info.get(m).getName().equals("id")) { // 判断是否为省节点id
// System.out.println(info.get(m).getText());
pro_id = Integer.valueOf(info.get(m).getText());
}
// System.out.println("===========1==========");
if (info.get(m).getName().equals("code")) { // 判断是否为省节点code
// System.out.println(info.get(m).getText());
pro_code = info.get(m).getText();
}
// System.out.println("===========2==========");
if (info.get(m).getName().equals("cn")) { // 判断是否为省节点中文名
// System.out.println(info.get(m).getText());
pro_name = info.get(m).getText();
}
if (info.get(m).getName().equals("cities")) { // 判断是否为市级节点
List<Element> cityList = info.get(m).elements(); // 市级节点的子节点集合
Queue<City> list3 = new LinkedList<City>();
for (int l = 0; l < cityList.size(); l++) { // 遍历市级节点的子节点
// System.out.println(cityList.get(l).getName());
if (cityList.get(l).getName().equals("id")) { // 判断是否为市节点id
// System.out.println("========"+cityList.get(l).getText());
city_id = (String) (pro_code+String.format("%02d", Integer.valueOf(cityList.get(l).getText())));
System.out.println(city_id);
}
// System.out.println("===========1==========");
if (cityList.get(l).getName().equals("cn")) { // 判断是否为市节点名字
// System.out.println(cityList.get(l).getText());
city_name = cityList.get(l).getText();
}
if (cityList.get(l).getName().equals("districts")) {
List<Element> dList = cityList.get(l).elements();
Queue<District> list4 = new LinkedList<District>();
for (int n = 0; n < dList.size(); n++) {
if (dList.get(n).getName().equals("id")) { // 判断是否为区县节点id
// System.out.println("========"+cityList.get(l).getText());
d_id = (String) (city_id+String.format("%02d", Integer.valueOf(dList.get(n).getText())));
// System.out.println(d_id);
}
// System.out.println("===========1==========");
if (dList.get(n).getName().equals("cn")) { // 判断是否为区县节点名字
// System.out.println(cityList.get(l).getText());
d_name = dList.get(n).getText();
}
}
District district = new District(d_id, d_name, city_id);
list4.add(district);
System.out.println(list4);
try {
new InsertDistrictDao().add(list4);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
City city = new City(city_id, city_name, pro_id);
list3.add(city);
System.out.println(list3);
try {
new InsertCityDao().add(list3);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Province province = new Province(pro_id, pro_code, pro_name);// 创建省份实体对象
list2.add(province); // 添加省份信息到集合
System.out.println(list2);
try {
new InsertProvinceDao().add(list2); // 调用添加省份方法
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
} catch (DocumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
以上是我的一些见解,如有错误欢迎指正。