java org.jdom.IllegalAddException:内容已经有一个现有的父“根”

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6851711/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 17:35:41  来源:igfitidea点击:

org.jdom.IllegalAddException: The Content already has an existing parent "root"

javaxmlsplitjdom

提问by kpr

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.

我正在尝试使用 jDOM 拆分一个大型 XML 文件(500mb)(我知道我可能应该尝试 SAX 但......)但我得到 org.jdom.IllegalAddException:内容已经有一个现有的父“根”异常,如图所示在下面的代码中。

sample xml and code are below. I believe all index checks and other trivial stuff is correct.

示例 xml 和代码如下。我相信所有索引检查和其他琐碎的东西都是正确的。

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;
}

回答by forty-two

You just need to detach() the element from its parent before you insert it in another document.

在将元素插入另一个文档之前,您只需要从其父元素中分离()该元素。

回答by alfiogang

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.

在 JDOM 实现中,每个元素都获得到父元素的链接:在新目标中添加元素之前,您必须从原始结构中分离元素。

Element elemCopy = (Element)element.clone();
elemCopy.detach();
destination.addContent(elemCopy);

回答by mkuzela

Replacing element in JDOM :

替换 JDOM 中的元素:

element.removeContent();

int size =  frEl.getContentSize();

for(int count = 0; count < size; count++) {
        element.addContent(frEl.getContent(0).detach());
}

回答by Swamy

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());
}