We are using the Java 8 and XML Stream API of Java to merge two xmls in a single threaded application.
Below are the two sample input xmls which I am trying to merge to the final xml. In both below sample xml html_tabs is common element so in the final XML there must be only one html_tabs element.
Sample XML 1
-----------------------
<?xml version='1.0' encoding='UTF-8'?>
<html_tabs lastRefreshDataDate="">
<tab code="H_test_1" companyCode="H_test_1"
id="H_test_1">
<table>
<tr><td>testing1 template</td></tr>
</table>
</tab>
</html_tabs>
Sample XML2
-----------------------
<?xml version='1.0' encoding='UTF-8'?>
<html_tabs lastRefreshDataDate="">
<tab code="H_test_2" companyCode="H_test_2"
id="H_test_2">
<table>
<tr><td>testing2 template</td></tr>
</table>
</tab>
</html_tabs>
Merged XML
---------------
<?xml version='1.0' encoding='UTF-8'?>
<html_tabs lastRefreshDataDate="">
<tab code="H_test_1" companyCode="H_test_1"
id="H_test_1">
<table>
<tr><td>testing1 template</td></tr>
</table>
</tab>
<tab code="H_test_2" companyCode="H_test_2"
id="H_test_2">
<table>
<tr><td>testing2 template</td></tr>
</table>
</tab>
</html_tabs>
Below is the code using which I am trying to merge two xml's by skipping the html_tabs element. I have skipped the import statement to keep the question short.
public class MergeXML1 {
/**
* @param args
*/
public static void main(String[] args) throws Exception {
XMLEventWriter eventWriter;
XMLEventFactory eventFactory;
XMLOutputFactory outputFactory = XMLOutputFactory.newInstance();
XMLInputFactory inputFactory = XMLInputFactory.newInstance();
eventWriter = outputFactory.createXMLEventWriter(new FileOutputStream("testMerge1.xml"));
eventFactory = XMLEventFactory.newInstance();
// Create and write Start Tag
XMLEvent statAbEvent = eventFactory.createStartDocument();
eventWriter.add(statAbEvent);
statAbEvent = eventFactory.createStartElement(StringUtils.EMPTY, StringUtils.EMPTY, "html_tabs");
eventWriter.add(statAbEvent);
statAbEvent = eventFactory.createAttribute("lastRefreshDataDate", StringUtils.EMPTY);
eventWriter.add(statAbEvent);
String[] filenames = new String[]{"4102530_1_statabfinsum.xml","4102530_2_statabfinsum.xml"};
for (String filename : filenames) {
XMLEventReader test = inputFactory.createXMLEventReader(filename, new FileInputStream(filename));
System.out.println("read the first file : " + filename);
while (test.hasNext()) {
XMLEvent event = test.nextEvent();
if (event.getEventType() != XMLEvent.START_DOCUMENT && event.getEventType() != XMLEvent.END_DOCUMENT) {
if (event.isStartElement()) {
StartElement startElement = event.asStartElement();
System.out.println("element name:" + startElement.getName().getLocalPart());
if (!startElement.getName().getLocalPart().equals("html_tabs")) {
eventWriter.add(event);
continue;
} else {
continue;
}
}
eventWriter.add(event);
}
}
test.close();
}
eventWriter.add(eventFactory.createEndElement("", "", "html_tabs"));
eventWriter.add(eventFactory.createEndDocument());
eventWriter.close();
}
}
Using above source code when am trying to merge two files it is throwing exception.
Exception in thread "main" javax.xml.stream.XMLStreamException: Trying to output second root, <tab>
at com.ctc.wstx.sw.BaseStreamWriter.throwOutputError(BaseStreamWriter.java:1589)
at com.ctc.wstx.sw.BaseStreamWriter.throwOutputError(BaseStreamWriter.java:1596)
at com.ctc.wstx.sw.BaseStreamWriter.reportNwfStructure(BaseStreamWriter.java:1624)
at com.ctc.wstx.sw.BaseNsStreamWriter.checkStartElement(BaseNsStreamWriter.java:483)
at com.ctc.wstx.sw.SimpleNsStreamWriter.writeStartOrEmpty(SimpleNsStreamWriter.java:257)
at com.ctc.wstx.sw.BaseNsStreamWriter.writeStartElement(BaseNsStreamWriter.java:325)
at org.codehaus.stax2.ri.Stax2EventWriterImpl.add(Stax2EventWriterImpl.java:100)
at com.citi.research.distribution.tasks.downloadtasks.MergeXML1.main(MergeXML1.java:60)
I am not able to find out what is wrong with above code due to which the exception is coming.
Based on examining your code, it appears you copied the final EndElement
from the first file to the output, putting you back at the top level. When you then tried to write the (correct) StartElement
from the second file, you were trying to insert this at root level.
Filter out (i.e. do not write) the EndElement
from the first file.