Search code examples
javaxmldomdomexception

DOMException at appendChild


I'm trying to modify an XML document using DOM by replacing some Elements in it, but I'm getting the following Exception:

03-10 10:49:20.943: W/System.err(22584):    org.w3c.dom.DOMException
03-10 10:49:20.943: W/System.err(22584):    at org.apache.harmony.xml.dom.InnerNodeImpl.insertChildAt(InnerNodeImpl.java:118)
03-10 10:49:20.943: W/System.err(22584):    at org.apache.harmony.xml.dom.InnerNodeImpl.appendChild(InnerNodeImpl.java:52)

The XML document has the following hierarchy:

<?xml version="1.0" encoding="UTF-8"?>
<msg>
    <header>
        <method>Call</method>
    </header>
</msg>

And I'm trying to replace the Element header by another one using replaceChild() method:

doc.replaceChild(header, (Element)doc.getElementsByTagName("header").item(0));

but I'm getting the above Exception. So, I traced the Exception to see where it is got thrown and that led me to the following line in org.apache.harmony.xml.dom.InnerNodeImpl Class:

public Node removeChild(Node oldChild) throws DOMException {

    LeafNodeImpl oldChildImpl = (LeafNodeImpl) oldChild;
    if (oldChildImpl.document != document) {
        throw new DOMException(DOMException.WRONG_DOCUMENT_ERR, null);
    }

    if (oldChildImpl.parent != this) {
        throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR, null); // This is where the Exception got thrown
    }

    int index = oldChildImpl.index;
    children.remove(index);
    oldChildImpl.parent = null;
    refreshIndices(index);
    return oldChild;

}

which means that it can't recognize the Element header as a child Element of the Document which is Incorrect, so, what am I missing here?!!

For reference, the following is my whole method I'm using in this process:

private void forming_and_sending_xml(String message, Element header){

    Document doc = null;
    try {
        doc = loadXMLFromString(message);
    } catch (Exception e) {
        e.printStackTrace();
    }
    doc.getDocumentElement().normalize();
    doc.replaceChild(header, (Element)doc.getElementsByTagName("header").item(0)); // this is where I got the Exception

}

UPDATE

I changed the way to replace the element, I used importNode to add the Node to the document and then I separated the replacement process to (remove -> add), which enabled me to fix all issues related to the remove process and now the Element is being removed successfully but the doc doesn't approve to add the new Element and it throws the same Exception that mentioned above.

My new method:

private void forming_and_sending_xml(String message, Element header){

    Document doc = null;
    try {
        doc = loadXMLFromString(message);
    } catch (Exception e) {
        e.printStackTrace();
    }
    doc.getDocumentElement().normalize();
    doc.importNode(header, true);
    Element header_holder = (Element)doc.getElementsByTagName("header").item(0);
    header_holder.getParentNode().removeChild(header_holder); // this removes the Element from the Doc succeffully
    doc.getDocumentElement().appendChild(header); // this is where the Exception is got thrown now

}

Solution

  • I guess there was two errors here:

    1. The new <header> element must be imported in to the existing document (as already disucssed in the comments), and

    2. The oldChild node must be an immediate child of the context node, not a grandchild as it is in the example. Replace

      doc.replaceChild(header, (Element)doc.getElementsByTagName("header").item(0)); 
      

      with

      doc.getDoumentElement().
         replaceChild(doc.importNode(header, true), 
                      (Element)doc.getElementsByTagName("header").item(0));