Combining multiple XML files in Java

I was looking for the best way to do this, but I cannot find a clear answer on how this should be done.

I have an Arraylist of Files in my Java code representing a list of xml files to be combined and written to a new XML file. This is not a fixed list of lengths, I estimate that it will be between 2-10 files. All of these files have a very similar document structure, but some attributes should be summarized when merging. For instance:

File1

<events> <commandEvents date="2013-07-16"> <commandEvent count="1" commandId="update"/> <commandEvent count="1" commandId="debug"/> <commandEvent count="3" commandId="resume"/> </commandEvents> </events> 

File 2

 <events> <commandEvents date="2013-07-16"> <commandEvent count="2" commandId="resume"/> </commandEvents> <commandEvents date="2013-07-15"> <commandEvent count="2" commandId="resume"/> <commandEvent count="1" commandId="update"/> </commandEvents> </events> 

Result

 <events> <commandEvents date="2013-07-16"> <commandEvent count="1" commandId="update"/> <commandEvent count="1" commandId="debug"/> <commandEvent count="5" commandId="resume"/> </commandEvents> <commandEvents date="2013-07-15"> <commandEvent count="2" commandId="resume"/> <commandEvent count="1" commandId="update"/> </commandEvents> </events> 

To clarify, merging should occur in commandEvents [@date] / commandEvent [@commandId]. The commandEvent elements have a few more attributes, but they are the same for each element, so I omitted them here. Not all dates will be available in every document.

At first I found some answers to go the XSLT path, but I'm pretty confused by the XSLT syntax for this. Although I'm not quite sure of the sizes these files can have, I would be very surprised that they will be> 1mb, so a Java DOM parser like JDOM or XOM can work, but I have to load all of these files into the same time or iteration in pairs.

What is considered the best way to do this? And if XSLT is considered the best solution, can you give me some tips on this?

+4
source share
2 answers

Here's a simple merge in which all the children of a node root in one document are joined to the node root of the second document:

 public static void mergeSecondLevel(Document from, Document to) { Element fromRoot = from.getDocumentElement(); Element toRoot = to.getDocumentElement(); Node child = null; while ((child = fromRoot.getFirstChild()) != null) { to.adoptNode(child); toRoot.appendChild(child); } } 

If you try to do some processing on the nodes before merging them (you say that some attributes should be summarized), then this will not be enough. There's linked mail that covers using XPath to retrieve nodes, but even then you have to write logic to ensure the correct updates.

+3
source

Check out XmlCombiner , which is a Java library that implements XML merging and allows you to add a filter in which you can specify the logic for summing the count attribute values.

Here is the code to initialize the library:

 import org.atteo.xmlcombiner.XmlCombiner; // create combiner specifying the attributes which are used as a keys XmlCombiner combiner = new XmlCombiner(Lists.newArrayList("date", "commandId")); // add the filter combiner.setFilter(filter); // combine files combiner.combine(firstFile); combiner.combine(secondFile); // store the result combiner.buildDocument(resultFile); 

And here is the code for the filter itself:

 XmlCombiner.Filter filter = new XmlCombiner.Filter() { @Override public void postProcess(Element recessive, Element dominant, Element result) { if (recessive == null || dominant == null) { return; } Attr recessiveNode = recessive.getAttributeNode("count"); Attr dominantNode = dominant.getAttributeNode("count"); if (recessiveNode == null || dominantNode == null) { return; } int recessiveValue = Integer.parseInt(recessiveNode.getValue()); int dominantValue = Integer.parseInt(dominantNode.getValue()); result.setAttribute("count", Integer.toString(recessiveValue + dominantValue)); } }; 

Disclaimer: I am the author of XmlCombiner.

+1
source

Source: https://habr.com/ru/post/1491697/


All Articles