org.jdom.IllegalAddException: The Content already has an existing parent "root"
13,234
Solution 1
You just need to detach() the element from its parent before you insert it in another document.
Solution 2
In JDOM implementation each element get link to parent: before you add an element in a new destination, you have to detach element from original structure.
Element elemCopy = (Element)element.clone();
elemCopy.detach();
destination.addContent(elemCopy);
Solution 3
Replacing element in JDOM :
element.removeContent();
int size = frEl.getContentSize();
for(int count = 0; count < size; count++) {
element.addContent(frEl.getContent(0).detach());
}
Solution 4
If it is list of elements, you may need to do something similar to following.
for (int count = 0; count < resultEle.size(); count++) {
destDocument.getRootElement().getChild("result").addContent(resultEle.get(count).detach());
}
![Admin](/assets/logo_square_200-5d0d61d6853298bd2a4fe063103715b4daf2819fc21225efa21dfb93e61952ea.png)
Author by
Admin
Updated on June 13, 2022Comments
-
Admin about 2 years
I am trying to split a large XML file (500mb) using jDOM (I know I should probably try SAX but ...) but I am getting org.jdom.IllegalAddException: The Content already has an existing parent "root" exception as shown in the code below.
sample xml and code are below. I believe all index checks and other trivial stuff is correct.
Thanks!!!
first of all sorry for the large amount of code.
<root> <metadata><md1>...</md1><md2>...</md2><metadata> <someOtherInfo><soi_1>...</soi_1></someOtherInfo> <collection> <item id="1">...</item><item id="2">...</item><item id="2">...</item> </collection> </root> split() { final String[] nodeNames = XmlUtils.getNodeNames(elementXpath); // returns {root, collection, item} // creates tree of //<root> // <metadata><md1>...</md1><md2>...</md2><metadata> // <someOtherInfo><soi_1>...</soi_1></someOtherInfo> // <collection> final Element originalDestination = importNodes(sourceDocument, nodeNames); Element destination = null; // traverses to "collection" element Element source = sourceDocument.getRootElement(); for (int tempCount = 1; tempCount < nodeNames.length - 1; ++tempCount) { source = source.getChild(nodeNames[tempCount]); } // get all "collection/item" elements for (Object obj : source.getChildren(nodeNames[nodeNames.length - 1])) { // makes sure that each out file has batchSize no of elements if (groupCount % batchSize == 0) { if (destination != null) { // traverse and go back up to the root Element root = destination; while (root.getParentElement() != null) { root = root.getParentElement(); } // this is where I get -- org.jdom.IllegalAddException: The Content already has an existing parent "root" -- exception final Document destDocument = new Document(destination); // write file to disk and reset counters } else { // create complete clone of originalDestination so that even its parents are cloned destination = createClone(originalDestination, nodeNames); } } // add this "item" element to destination "collection" element final Element element = (Element) obj; destination.addContent(((Element) element.clone())); count++; groupCount++; } if (groupCount > 0) { // write remaining "items" to file } } private Element createClone(final Element source, final String[] nodeNames) { Element destination = source; while (destination.getParentElement() != null) { destination = destination.getParentElement(); } destination = (Element) destination.clone(); for (int tempCount = 1; tempCount < nodeNames.length - 1; ++tempCount) { destination = destination.getChild(nodeNames[tempCount]); } return destination; } private Element importNodes(final Document document, final String[] nodeNames) { Element source = document.getRootElement(); if (!source.getName().equals(nodeNames[0])) { return null; } Element destination = null; for (int count = 0; count < (nodeNames.length - 1); count++) { if (count > 0) { source = source.getChild(nodeNames[count]); } final Element child = new Element(nodeNames[count]); if (destination != null) { destination.setContent(child); } destination = child; // copy attributes -- don't want to clone here since this is one of the ancestors of "item" for (Object objAttb : source.getAttributes()) { Attribute attb = (Attribute) objAttb; destination.setAttribute(attb.getName(), attb.getValue()); } // this is for <metadata> and <soneInfo> elements for (Object obj : source.getChildren()) { final Element childToClone = (Element) obj; if (!childToClone.getName().equals(nodeNames[count + 1]) && (ignoreWhiteSpaceNodes ? !childToClone.getName() .equals("#text") : true)) { final Element clone = (Element) childToClone.clone(); destination.addContent(clone); } } } return destination; }