I am trying to merge two xmls in Java. I am using STaX API to write these XMLs. I searched a lot on internet on how to merge xmls but none seems as straight forward as C#. Is there any straight-forward way of doing this in Java using StAX? Probably xslt would not be the right solution since the file size can be big.
File1.xml
<TestCaseBlock>
<TestCase TestCaseID="1">
<Step ExecutionTime="2011-03-29 12:08:31 EST">
<Status>Passed</Status>
<Description>foo</Description>
<Expected>foo should pass</Expected>
<Actual>foo passed</Actual>
</Step>
</TestCase>
</TestCaseBlock>
File2.xml
<TestCaseBlock>
<TestCase TestCaseID="2">
<Step ExecutionTime="2011-03-29 12:08:32 EST">
<Status>Failed</Status>
<Description>test something</Description>
<Expected>something expected</Expected>
<Actual>not as expected</Actual>
</Step>
</TestCase>
</TestCaseBlock>
Merged.xml
<TestCaseBlock>
<TestCase TestCaseID="1">
<Step ExecutionTime="2011-03-29 12:08:33 EST">
<Status>Passed</Status>
<Description>foo</Description>
<Expected>foo should pass</Expected>
<Actual>foo passed</Actual>
</Step>
</TestCase>
<TestCase TestCaseID="2">
<Step ExecutionTime="2011-03-29 12:08:34 EST">
<Status>Failed</Status>
<Description>test something</Description>
<Expected>something expected</Expected>
<Actual>not as expected</Actual>
</Step>
</TestCase>
</TestCaseBlock>
To add files click anywhere in the blue area or on the Browse for file button to upload or drag and drop them. You can also add the documents by entering their URL in the URL cell. Click on the Merge button. Your MPP file will be uploaded and combined to the result format.
XML (Extensible Markup Language) is a very popular simple text-based language that can be used as a mode of communication between different applications. It is considered as a standard means to transport and store data.
I have a solution that works for me. Now experts, please advise if this is the way to go.
Thanks, -Nilesh
XMLEventWriter eventWriter;
XMLEventFactory eventFactory;
XMLOutputFactory outputFactory = XMLOutputFactory.newInstance();
XMLInputFactory inputFactory = XMLInputFactory.newInstance();
eventWriter = outputFactory.createXMLEventWriter(new FileOutputStream("testMerge1.xml"));
eventFactory = XMLEventFactory.newInstance();
XMLEvent newLine = eventFactory.createDTD("\n");
// Create and write Start Tag
StartDocument startDocument = eventFactory.createStartDocument();
eventWriter.add(startDocument);
eventWriter.add(newLine);
StartElement configStartElement = eventFactory.createStartElement("","","TestCaseBlock");
eventWriter.add(configStartElement);
eventWriter.add(newLine);
String[] filenames = new String[]{"test1.xml", "test2.xml","test3.xml"};
for(String filename:filenames){
XMLEventReader test = inputFactory.createXMLEventReader(filename,
new FileInputStream(filename));
while(test.hasNext()){
XMLEvent event= test.nextEvent();
//avoiding start(<?xml version="1.0"?>) and end of the documents;
if (event.getEventType()!= XMLEvent.START_DOCUMENT && event.getEventType() != XMLEvent.END_DOCUMENT)
eventWriter.add(event);
eventWriter.add(newLine);
test.close();
}
eventWriter.add(eventFactory.createEndElement("", "", "TestCaseBlock"));
eventWriter.add(newLine);
eventWriter.add(eventFactory.createEndDocument());
eventWriter.close();
General solution still would be XSLT, but you'd need to combine two files into one big XML first with a wrapper element (XSLT works with one input source).
<root>
<TestCaseBlock>
<TestCase TestCaseID="1">
...
</TestCase>
</TestCaseBlock>
<TestCaseBlock>
<TestCase TestCaseID="2">
...
</TestCase>
</TestCaseBlock>
</root>
Then just do XSLT for match="//TestCase", and dump all test cases out, ignoring what test case block they belong to.
And don't worry about performance until you have tried. XML APIs in JAva are getting much better than in 2003.
This is stylesheet you need:
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" encoding="UTF-8" indent="yes"/>
<xsl:template match="/">
<TestCaseBlock>
<xsl:apply-templates/>
</TestCaseBlock>
</xsl:template>
<xsl:template match="//TestCase">
<xsl:copy-of select="."/>
</xsl:template>
</xsl:stylesheet>
Tested, it works.
BTW, this XSLT was compiled and executed on this (small) example in 1ms.
If structure is regular enough so you can use data binding, I would actually consider binding XML from both files into objects using JAXB, then merging objects, serializing back as XML. If file sizes are big you can also just bind sub-trees; for this you use XMLStreamReader (from Stax api, javax.xml.stream) to iterate to element that is the root, bind that element (and its children) to object you want, iterate to next root element.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With