I have a List<String>
which contains the XML
events created as a part of the output from the JAXB Marshaling
approach. After completion of the JAXB Marshaling
process this List<String>
can contain large amounts of XML.
These XML
fragments so are part of a large XML. The large XML has some additional header elements so I am trying to create the large XML
using the XMLEventWriter
and trying to add the elements from my LIST<String>
but it does not work as expected and running into various errors.
I get the following error:
Exception in thread "main" javax.xml.stream.XMLStreamException: Trying to output second root
Following is the code I have:
import javax.xml.namespace.QName; import javax.xml.stream.*; import java.io.StringReader; import java.util.ArrayList; import java.util.List; public class TestMain { public static void main(String[] args) throws XMLStreamException { final XMLEventWriter xmlEventWriter = XMLOutputFactory.newInstance().createXMLEventWriter(System.out); final XMLEventFactory events = XMLEventFactory.newInstance(); List<String> eventList = new ArrayList<>(); eventList.add("<fragment><data>First Event</data></fragment>"); eventList.add("<fragment><data>Second Event</data></fragment>"); eventList.add("<another><data>Third Event</data></another>"); xmlEventWriter.add(events.createStartDocument()); xmlEventWriter.add(events.createStartElement(new QName("root"), null, null)); xmlEventWriter.add(events.createStartElement(new QName("fragments"), null, null)); for (String event : eventList) { final XMLEventReader xer = XMLInputFactory.newInstance().createXMLEventReader(new StringReader(event)); if (xer.peek().isStartDocument()) { xer.nextEvent(); xmlEventWriter.add(xer); } } xmlEventWriter.add(events.createEndDocument()); xmlEventWriter.add(events.createEndDocument()); xmlEventWriter.close(); } }
Following is the output I am expecting:
<root> <fragments> <fragment> <data>First Event</data> </fragment> <fragment> <data>Second Event</data> </fragment> <another> <data>Third Event</data> </another> </fragments> </root>
I looked into XMLStreamWriter
but I got to know that this cannot be done using that. I am not particular about XMLEventWriter
. All I want to is get the required output using any of the approaches/libraries.
Can someone please help me with this? I just want to add the XML
from my List
to XMLEventWriter
which has been created already with few Nodes.
Advertisement
Answer
First, your ending events are wrong:
xmlEventWriter.add(events.createEndDocument()); xmlEventWriter.add(events.createEndDocument());
They should be:
xmlEventWriter.add(events.createEndElement(new QName("fragments"), null)); xmlEventWriter.add(events.createEndElement(new QName("root"), null)); xmlEventWriter.add(events.createEndDocument());
Second, the issue is that the xer
event reader ends with an “End Document” event that you don’t want copied, so you need to filter it out.
To do that, wrap xer
with a delegate that ends the event stream when the “End Document” event is reached:
xer = new EventReaderDelegate(xer) { @Override public boolean hasNext() { if (! super.hasNext()) return false; try { return ! super.peek().isEndDocument(); } catch (@SuppressWarnings("unused") XMLStreamException ignored) { return true; } } };