Search code examples
javaxmljaxbstax

Chunking XML with XMLStreamReader failing


I am trying to chunk out a big XML into smaller pieces with StAX and JAXB. Here is the sample XML that I am working on:

<asset>
    <entity>
        <record>
            <field>
                <id>remarks</id>
                <value>ready to test1</value>
            </field>
        </record>
        <record>
            <field>
                <id>input_quarter</id>
                <value>Jun-Sep</value>
            </field>
        </record>
    </entity>
</asset>

I want to read on record at a time and process it. Here is how I am doing it:

ClassPathResource classPathResource = new ClassPathResource("samples/form2/data/test.xml");
XMLInputFactory xmlInputFactory = XMLInputFactory.newFactory();
xmlInputFactory.setProperty(XMLInputFactory.IS_COALESCING, true);
XMLStreamReader xmlStreamReader = xmlInputFactory.createXMLStreamReader(classPathResource.getInputStream());

JAXBContext jaxbContext = JAXBContext.newInstance(EntityRecordData.class);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
while(xmlStreamReader.hasNext()){
    int eventType = xmlStreamReader.next();
    switch (eventType) {
    case XMLEvent.START_ELEMENT:
        System.out.println("Element: "+xmlStreamReader.getLocalName());
        if("record".equals(xmlStreamReader.getLocalName())){
            Object unmarshal = unmarshaller.unmarshal(xmlStreamReader);
        }
        break;
    case XMLEvent.CHARACTERS: 
        String text = xmlStreamReader.getText();
        System.out.println("Text: "+text);
        break;
    case XMLEvent.END_ELEMENT: 
        break;
    default : break;
    }
}
xmlStreamReader.close();

I am able to read first record properly. But after reading the first record, the stream is moving to inside the second record instead of . And hence I am not able to process the second record. I am not sure where I am going wrong. Please help.


Solution

  • Here is the solution:

    ClassPathResource classPathResource = new ClassPathResource("samples/form2/data/test.xml");
        XMLInputFactory xmlInputFactory = XMLInputFactory.newFactory();
        xmlInputFactory.setProperty(XMLInputFactory.IS_COALESCING, true);
        XMLStreamReader xmlStreamReader = xmlInputFactory.createXMLStreamReader(classPathResource.getInputStream());
    
        JAXBContext jaxbContext = JAXBContext.newInstance(EntityRecordData.class);
        Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
        int eventType = xmlStreamReader.next();
        while(true){
            switch (eventType) {
            case XMLEvent.START_ELEMENT:
                System.out.println("Element: "+xmlStreamReader.getLocalName());
                if("record".equals(xmlStreamReader.getLocalName())){
                    JAXBElement<EntityRecordData> unmarshal = unmarshaller.unmarshal(xmlStreamReader, EntityRecordData.class);
                    final List<IFieldData> fields = unmarshal.getValue().getFields();
                    System.out.println("**"+fields.get(0).getId());
                } else {
                    eventType = xmlStreamReader.next();
                }
                break;
            case XMLEvent.CHARACTERS: 
                String text = xmlStreamReader.getText();
                System.out.println("Text: "+text);
                eventType = xmlStreamReader.next();
                break;
            case XMLEvent.END_ELEMENT: 
                //System.out.println("End: "+xmlStreamReader.getLocalName());
                eventType = xmlStreamReader.next();
                break;
            default : 
                break;
            }
    
            if(!xmlStreamReader.hasNext()){
                break;
            }
        }
        xmlStreamReader.close();