Stax XMLStreamReader check for the next event without moving ahead

“Going back” in a stream implies some kind of memory, so there is no point in sticking to the most memory-efficient tool.

XMLEventReader can handle this with ease:

public class Main {

    public static void main(String args[]) throws Exception {
        Unmarshaller aUnmarshaller = JAXBContext.newInstance(A.class).createUnmarshaller();
        Unmarshaller bUnmarshaller = JAXBContext.newInstance(B.class).createUnmarshaller();
        Unmarshaller cUnmarshaller = JAXBContext.newInstance(C.class).createUnmarshaller();
        try (InputStream input = Main.class.getResourceAsStream("InputEPCISEvents.xml")) {
            XMLEventReader reader = XMLInputFactory.newInstance().createXMLEventReader(input);
            while (reader.hasNext()) {
                XMLEvent event = reader.peek();
                if (event.isStartElement()) {
                    switch (event.asStartElement().getName().getLocalPart()) {
                        case "a" -> System.out.println(aUnmarshaller.unmarshal(reader));
                        case "b" -> System.out.println(bUnmarshaller.unmarshal(reader));
                        case "c" -> System.out.println(cUnmarshaller.unmarshal(reader));
                    }
                }
                reader.next();
            }
        }
    }

    @XmlAccessorType(XmlAccessType.FIELD)
    static class ABC {
        String name;
        String age;

        public String toString() {
            return getClass().getSimpleName() + "{name="" + name + "", age="" + age + "}";
        }
    }
    @XmlRootElement static class A extends ABC {}
    @XmlRootElement static class B extends ABC {}
    @XmlRootElement static class C extends ABC {}
}

Output:

C{name="CName', age="CAge}
B{name="BName', age="BAge}
A{name="AName', age="AAge}
B{name="BName', age="BAge}

By the way, your XML needs to be wrapped in a parent element as it contains more than one root element.

Leave a Comment