【问题标题】:JAXB with XMLStreamReader and StreamFilter does not finalize带有 XMLStreamReader 和 StreamFilter 的 JAXB 未完成
【发布时间】:2020-06-19 00:07:43
【问题描述】:

我尝试将XMLStreamReaderStreamFilter 结合使用来部分读取XML 文件。其核心方法如下所示:

public ScheduleList getScheduleListFromXMLFile(File scheduleListFile, ScheduleTimeRange scheduleTimeRange) {

    ScheduleList scheduleList = null;
    try {
        JAXBContext context = JAXBContext.newInstance(this.getJAXBContextClasses());
        Unmarshaller unMarsh = context.createUnmarshaller();

        InputStream inputStream = new FileInputStream(scheduleListFile);

        XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
        XMLStreamReader xmlStreamReader = xmlInputFactory.createXMLStreamReader(inputStream);

        // --- Check if a system state filter is to be applied ------------
        if (scheduleTimeRange!=null && scheduleTimeRange.isValidTimeRange()==true) {
            // --- Add a filter to the XMLStreamReader -------------------- 
            xmlStreamReader = xmlInputFactory.createFilteredReader(xmlStreamReader, new ScheduleList_XMLStreamFilter(scheduleTimeRange));
        }

        JAXBElement<ScheduleList> jaxbElement = (JAXBElement<ScheduleList>) unMarsh.unmarshal(xmlStreamReader);
        xmlStreamReader.close();
        inputStream.close();

        if (jaxbElement!=null) {
            // --- Check if the loaded object is of the required type -----
            Object loadedObject = jaxbElement.getValue();
            if (loadedObject instanceof ScheduleList) {
                scheduleList = (ScheduleList) loadedObject;
            } else {
                JOptionPane.showMessageDialog(this.getOwnerFrame(), getWarningString(), "Wrong object type", JOptionPane.ERROR_MESSAGE);
            }
        }

    } catch (JAXBException e) {
        if (e.getCause() instanceof InstantiationException) {
            // --- Try to load based on the previous version ---
            scheduleList = EomModelUpdater.getScheduleListFromXMLFile(scheduleListFile);
        } else {
            e.printStackTrace();
        }

    } catch (IOException | XMLStreamException ex) {
        ex.printStackTrace();

    } finally {
        convertToTreeScheduleList(scheduleList);            
    }
    return scheduleList;
}

如果 'scheduleTimeRange' 为 null,则不会应用任何过滤器并且解组操作可以正常工作。如果应用了过滤器,则操作不会从方法/行返回

JAXBElement<ScheduleList> jaxbElement = (JAXBElement<ScheduleList>) unMarsh.unmarshal(xmlStreamReader);

,即使应用的过滤器也告诉我已到达文档末尾。实现 StreamFilter 的过滤器的 'accept(XMLStreamReader reader)' 方法如下所示:

public boolean accept(XMLStreamReader reader) {

    if (reader.isStartElement()==true) {
        // --- Starting elements --------------------
        if (reader.getLocalName().equals("TechnicalSystemStateList")==true) {
            // --- Set default accept ---------------
            this.acceptSystemState = true;

        } else if (reader.getLocalName().equals("GlobalTime")==true) {
            // --- Check if TSSE can be accepted ---- 
            try {
                String globalTimeText = reader.getElementText();
                Long globalTime = this.parseLong(globalTimeText);
                if (globalTime!=null) {
                    this.acceptSystemState = this.scheduleTimeRange.isWithinTimeRange(globalTime);
                }

            } catch (XMLStreamException xmlStreamEx) {
                xmlStreamEx.printStackTrace();
            }
        }

    } else if (reader.isEndElement()==true) {
        // --- Ending elements ----------------------
        if (reader.getLocalName().equals("TechnicalSystemStateList")) {
            return this.acceptSystemState;
        }
    }


    try {
        if (reader.hasNext()==false) {
            System.out.println("Found end of document");

        }

    } catch (XMLStreamException e) {
        e.printStackTrace();
    }

    return true;
}

我不知道这里出了什么问题,如果有提示,我会很高兴的。 目前,我们正在使用 Java 8 (jdk1.8.0_191)。

【问题讨论】:

    标签: java jaxb xmlstreamreader


    【解决方案1】:

    在寻找 XMLStreamReader 没有终止的原因几个小时后,我在 StAXStreamConnector 的 bridge() 方法中找到了答案。正如在下面的代码中看到的那样,只有当我们位于元素的末尾并且深度为 0 时,while 循环才会终止。我对 StreamFilter 所做的(并且假设是正确的)是不接受那些结束标签,我的过滤条件发现“超出范围”。结果变量深度没有减少。

    我想知道为什么这个实现不寻找 END_DOCUMENT ...!?

                // --- some further code above ---
                OUTER:
                while(true) {
                    // These are all of the events listed in the javadoc for
                    // XMLEvent.
                    // The spec only really describes 11 of them.
                    switch (event) {
                        case XMLStreamConstants.START_ELEMENT :
                            handleStartElement();
                            depth++;
                            break;
                        case XMLStreamConstants.END_ELEMENT :
                            depth--;
                            handleEndElement();
                            if(depth==0)    break OUTER;
                            break;
                        case XMLStreamConstants.CHARACTERS :
                        case XMLStreamConstants.CDATA :
                        case XMLStreamConstants.SPACE :
                            handleCharacters();
                            break;
                        // otherwise simply ignore
                    }
                    event=staxStreamReader.next();
                }
                // --- some further code below ---
    
    

    最后,我编写了自己的 SAX 解析器/处理程序,以便能够过滤元素 - 与 JAXB 相比,这反过来提高了文件读取速度。

    【讨论】:

      猜你喜欢
      • 2014-05-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-23
      • 2019-11-01
      相关资源
      最近更新 更多