0
点赞
收藏
分享

微信扫一扫

事件驱动方式解析超大XML

三次方 2021-09-21 阅读 41
JavaJava web

在我们的实际开发过程中,有可能需要用到去解析超级大的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();
        }
    }
举报

相关推荐

0 条评论