在我们的实际开发过程中,有可能需要用到去解析超级大的XML文件,通常像XML解析大的方向上分类有两种:
项目中正好有一个需求,涉及到要解析大体积xml,体积在几百M左右,逻辑就是解析出所有的内容然后入库,下面代码是xml内容:
<NewDataSet>
<ds>
<ZF_BH>1201000010</ZF_BH>
<GZName>缝纫工</GZName>
<IsDE>1</IsDE>
<GZDE>10000.00</GZDE>
<FPDate>20170615</FPDate>
</ds>
……还有很多个<ds>
</NewDataSet>
解析逻辑是,每解析出1000条数据,然后保存到数据库,解析逻辑如下
public void parseAndInsert(String filePath) throws FileNotFoundException, XMLStreamException {
// System.out.println("解析开始……");
XMLInputFactory inputFactory = XMLInputFactory.newFactory();
List<Zfgwxxorg> list = new ArrayList<>();
try {
// 首先创建事件驱动的reader
XMLEventReader eventReader = inputFactory.createXMLEventReader(new FileInputStream(filePath));
// 按事件(可以理解成标记)逐行解析
while(eventReader.hasNext()) {
// 获取当前标记
XMLEvent event = eventReader.nextEvent();
// 如果是开始标签
if (event.isStartElement()) {
// 获取标签名称
String tag = event.asStartElement().getName().getLocalPart();
// 如果是实体元素, 则创建一个新元素并放入list中,ds标签包含一个实体所有的属性
if ("ds".equalsIgnoreCase(tag)) {
Zfgwxxorg domain = new Zfgwxxorg();
list.add(domain);
// 如果是编号标签
} else if ("ZF_BH".equalsIgnoreCase(tag)) {
// 获取编号标签中的属性值
String zfbh = eventReader.nextEvent().asCharacters().getData();
// 将list中最后一个实体设置值
list.get(list.size()-1).setZfbh(zfbh);
} else if ("GZName".equalsIgnoreCase(tag)) {
XMLEvent nextEvent = eventReader.nextEvent();
// 这里没有连续去获取是因为可能标签为<MR_YM/>,这种标签会被识别为开始标签,但是没有值
// 所以进行一个判断
if (nextEvent instanceof Characters) {
String gzName = nextEvent.asCharacters().getData();
list.get(list.size()-1).setGzname(gzName);;
}
} else if ("IsDE".equalsIgnoreCase(tag)) {
XMLEvent nextEvent = eventReader.nextEvent();
if (nextEvent instanceof Characters) {
String isDe = nextEvent.asCharacters().getData();
list.get(list.size()-1).setIsde(isDe);;
}
} else if ("GZDE".equalsIgnoreCase(tag)) {
XMLEvent nextEvent = eventReader.nextEvent();
if (nextEvent instanceof Characters) {
String gzde = nextEvent.asCharacters().getData();
list.get(list.size()-1).setGzde(gzde);;
}
} else if ("FPDate".equalsIgnoreCase(tag)) {
XMLEvent nextEvent = eventReader.nextEvent();
if (nextEvent instanceof Characters) {
String fpDate = nextEvent.asCharacters().getData();
list.get(list.size()-1).setFpdate(fpDate);
}
}
// 假如是结束标签
} else if (event.isEndElement()) {
String tag = event.asEndElement().getName().getLocalPart();
// 假如是ds的结束标签,代表所有属性已经解析完毕
if ("ds".equalsIgnoreCase(tag)) {
// 这里给最后一个实体设置id
Zfgwxxorg last = list.get(list.size()-1);
last.setId(last.getZfbh()+last.getFpdate()); // 编号和年月为唯一值
// 每1000条保存一次
if (list.size() == 1000) {
zfgwxxorgDAO.saveAll(list);
list.clear();
}
}
}
}
// 解析完毕后, 不足1000条的,将剩下的入库
if (list.size() > 0) {
zfgwxxorgDAO.saveAll(list);
}
eventReader.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (XMLStreamException e) {
e.printStackTrace();
}
}