Merging multiple xmls using Java (Part-2)

In the previous post we have discussed about how we can collect tags by name in two xmls.

NodeList fNodes, sNodes;fNodes = fMsg.getElementsByTagName("person");sNodes = sMsg.getElementsByTagName("person");

Now we have fNodes and sNodes variables with elements by tag inside. We'll append the elements of one xml to the other xml.


for (int i = 0; i < sNodes.getLength(); i = i + 1) {       Node n = (Node) fMsg.importNode(sNodes.item(i), true);       fNodes.item(i).getParentNode().appendChild(n);}
Okay....!!!!!Everything is okay now.All we have to do is get the output from above implementation.First we'll create a StringWriter object and parse the fMsg object to it.Here we have to use the Transformer object in order to build the new xml.

StringWriter buf = new StringWriter();Transformer transformer = TransformerFactory.newInstance().newTransformer();transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");transformer.transform(new DOMSource(fMsg), new StreamResult(buf));<\br>String newBuf = buf.toString();System.out.println(newBuf);
So finally we get the output as described in the first post.You may wander how we can extend this to merge more than two xmls. The answer is simple.You just have to take two elements at a time and perform the above tasks and merge the final result.The implementation for multiple xmls as follows.Assume that you have xml strings in an arraylist named as collected messages.We'll collect the inputstreams of those xml strings using an arraylist named messages
First we'll create an Arraylist of Inputstreams. 


ArrayList<InputStream> messages = new ArrayList<>();collectedMessages.forEach(msg -> {      InputStream&nbsp= = new ByteArrayInputStream(msg.getBytes(StandardCharsets.UTF_8));      messages.add(inputStream);});
Next we'll initialize the document builders.



DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();domFactory.setIgnoringComments(true);DocumentBuilder builder = domFactory.newDocumentBuilder();
Everything is normal until now.In the first example we merged two xmls. But now we have multiple xmls. What can we do...!! The solution is simple we just have to take two at a time,process them,make one xml and process the new one with an unprocessed xml in arraylist. Let's try to implement the solution.First we'll create variables to keep track on what we are doing.



Document fMsg, sMsg;NodeList fNodes, sNodes;
We need a loop to iterate through the arraylist of inputstreams. We'll process first two xmls,make one xml and add it to the top of the arraylist removing first and second elements from the list. We can iterate until the size of arraylist become one.The remaining element in the arraylist is the final result.  

while (messages.size() > 1) {
        byte[] b = new byte[1024];
        fMsg = builder.parse(messages.get(0));
        sMsg = builder.parse(messages.get(1));
        fNodes = fMsg.getElementsByTagName(mergePath);
        sNodes = sMsg.getElementsByTagName(mergePath);
        for (int i = 0; i < sNodes.getLength(); i = i + 1) {
            Node n = (Node) fMsg.importNode(sNodes.item(i), true);
           fNodes.item(i).getParentNode().appendChild(n);
        }
        StringWriter buf = new StringWriter();
        Transformer transformer = TransformerFactory.newInstance().newTransformer();
        transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
        transformer.transform(new DOMSource(fMsg), new StreamResult(buf));
        String rootlessBuf = buf.toString();
        b = rootlessBuf.getBytes(StandardCharsets.UTF_8);
        InputStream xmlOutput = new ByteArrayInputStream(b);
        messages.remove(0);   
        messages.remove(0);
        messages.add(0, xmlOutput);
}
At the end we have messages array list which contains only one element.So we can convert that inputstream to string and get the output. 

Comments