我尝试将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)。

最佳答案

经过数小时的搜索,发现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相比,这反过来又提高了文件读取速度。

关于java - 带有XMLStreamReader和StreamFilter的JAXB无法完成,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/60560952/

10-10 06:57