How to Merge two XMLs in Java

拟墨画扇 提交于 2019-11-30 14:11:50

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.

Check XmlCombiner which is a Java library that implements XML merging in exactly this way. It is loosely based on a similar functionality offered by plexus-utils library.

In your case the tags should be also matched based on the value of the attribute 'TestCaseID'. Here is the full example:

import org.atteo.xmlcombiner.XmlCombiner;

// create combiner
XmlCombiner combiner = new XmlCombiner("TestCaseID");
// combine files
combiner.combine(firstFile);
combiner.combine(secondFile);
// store the result
combiner.buildDocument(resultFile);

Disclaimer: I am the author of the library.

m.genova

I think XSLT and SAX could be a solution.

If you'll work with Stream that STaX is solution, I read Sun tutorial, I think is very helpful: Sun Tutorail on STaX

Bye

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!