views:

760

answers:

2

I have an XML file below and I want to create multiple files:

<ParentNode>                                  file1:
    <ChildNode>                               <ParentNode>
        <node></node>                             <ChildNode>
    </childNode>                                      <node></node>
    <ChildNode>                                   </childNode>
        <node></node>                         </ParentNode>
    </childNode>                              file2:
    <ChildNode>                               <ParentNode>
        <node></node>                             <ChildNode>
    </childNode>                                      <node></node>
</ParentNode>                                      </childNode>
                                              </ParentNode>

I am trying to take the first child node from the original XML file and add it to a new one but I keep getting errors around replacing nodes.

I want to do something like the following

 DocumentBuilderFactory dbfac = DocumentBuilderFactory.newInstance();
 DocumentBuilder docBuilder = dbfac.newDocumentBuilder();
 Document newDocument;

 Node firstChild = document.getFirstChild();
 NodeList childNodes = firstChild.getChildNodes();

 Element parentNode;
 for (int i = 1; i < childNodes.getLength(); i++ ) {
     newDocument = docBuilder.newDocument();
     parentNode = newDocument.createElement("ParentNode");
     newDocument.appendChild(parentNode);
     newDocument.getFirstChild().appendChild(childNodes.item(i));
 }

but I get an error

org.w3c.dom.DOMException: WRONG_DOCUMENT_ERR: A node is used in a different document than the one that created it.

any help pointing in the right direction appreciated!

+1  A: 

Nodes in the DOM have a concept of their owning document (hence your WRONG_DOCUMENT_ERR).

So you need to import the node from the original DOM to your new one. See Document.importNode()

Brian Agnew
added line newDocument.importNode(childNodes.item(i), true); but still gives same error
Craig Angus
You took the *result* of importNode, right ?
Brian Agnew
No!, because I'm a complete idiot!Once I assigned the result I could then append it to the child node and voila theres the XML I need.i new I just needed nudged in the right direction Thanks
Craig Angus
Ah. That's good. A bit of a guess on my part that that was the problem, but glad it worked.
Brian Agnew
+1  A: 

From Java documentation,

Use cloneNode method.

SUMMARY:

public Node cloneNode(boolean deep)

Returns a duplicate of this node, i.e., serves as a generic copy constructor for nodes. The duplicate node has no parent; ( parentNode is null.).

Cloning an Element copies all attributes and their values, including those generated by the XML processor to represent defaulted attributes, but this method does not copy any text it contains unless it is a deep clone, since the text is contained in a child Text node. Cloning an Attribute directly, as opposed to be cloned as part of an Element cloning operation, returns a specified attribute ( specified is true). Cloning any other type of node simply returns a copy of this node.

Note that cloning an immutable subtree results in a mutable copy, but the children of an EntityReference clone are readonly . In addition, clones of unspecified Attr nodes are specified. And, cloning Document, DocumentType, Entity, and Notation nodes is implementation dependent.

EDIT :

import java.io.*;
import javax.xml.parsers.*;
import org.w3c.dom.*;
import org.xml.sax.*;
import javax.xml.transform.*; 
import javax.xml.transform.dom.DOMSource; 
import javax.xml.transform.stream.StreamResult;

public class Test{
 static public void main(String[] arg) throws Exception{

 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
 DocumentBuilder builder = factory.newDocumentBuilder();
 Document doc = builder.parse("foo.xml");

 TransformerFactory tranFactory = TransformerFactory.newInstance(); 
 Transformer aTransformer = tranFactory.newTransformer(); 


 NodeList list = doc.getFirstChild().getChildNodes();

 for (int i=0; i<list.getLength(); i++){
    Node element = list.item(i).cloneNode(true);

 if(element.hasChildNodes()){
   Source src = new DOMSource(element); 
   FileOutputStream fs=new FileOutputStream("k" + i + ".xml");
   Result dest = new StreamResult(fs);
   aTransformer.transform(src, dest);
   fs.close();
   }
   }

  }
}
adatapost
by changing to newDocument.getFirstChild().appendChild(childNodes.item(i).cloneNode(true));still get same error
Craig Angus
Thanks! Awesome answer, I was just looking to understand what was going wrong and you've gone and done all the work for me!
Craig Angus
You are welcome. Thanks @Craig.
adatapost