Domanda

Sto costruendo uno script che deve rattoppare i file XML, tra cui la sostituzione di una lista di elementi con un altro. La seguente funzione applica una patch (che coinvolge una lista vuota di elementi con lo stesso nome) sulla lista di elementi genitore dell'Elemento con lo stesso nome (eventualmente anche un elenco vuoto). (Questa è solo una piccola parte della logica patch).

Perché, quando si esegue il codice, ottengo il seguente errore?

org.w3c.dom.DOMException: NOT_FOUND_ERR: An attempt is made to reference a node in a context where it does not exist.
    at com.sun.org.apache.xerces.internal.dom.ParentNode.internalRemoveChild(ParentNode.java:503)
    at com.sun.org.apache.xerces.internal.dom.ParentNode.removeChild(ParentNode.java:484)
    at CombineSweeps$PTReplaceNodeList.apply(CombineSweeps.java:514)

(linea 514 è etichettato sotto.) Per quanto riguarda ho capito, ho appena verificato che l'elemento esiste (perché NodeList è vivo, il suo primo ingresso sarà sempre la prossima partita o null). È interessante notare che questo non è sempre un problema.

private static class PTReplaceNodeList extends PTBase {
    private final String name;
    private final String nextElement;
    private final List<Node> childList;

    ...

    int apply(Document document, Node parent, Node node_unused) {
        NodeList nodes;
        // A marker for where to insert our nodes.
        // We make a guess using nextElement (if null, means at end).
        Node refNode = null;
        if (parent instanceof Document) {   // root element
            Document parDoc = (Document) parent;
            nodes = parDoc.getElementsByTagName(name);
            if (nextElement != null) {
                refNode = parDoc.getElementsByTagName(nextElement).item(0);
            }
        } else {
            Element parElt = (Element) parent;
            nodes = parElt.getElementsByTagName(name);
            if (nextElement != null) {
                refNode = parElt.getElementsByTagName(nextElement).item(0);
            }
        }

        while (true) {
            // iterate through the list of nodes
            Node node = nodes.item(0);
            if (node == null) {
                break;
            }

            // Reliable guess: insert before node following last in list
            refNode = node.getNextSibling();

            parent.removeChild(node);  // line 514
        }

        for (Node child : childList) {
            Node imported = document.importNode(child, true);
            parent.insertBefore(imported, refNode);
        }
        return childList.size();
    }
}

Modifica:. Ho usato la seguente funzione in sostituzione del getElementsByTagName() (vedi risposta accettata)

/** Returns all direct children of node with name name.
 *
 * Note: not the same as getElementsByTagName(), which finds all descendants. */
static List<Node> getChildNodes( Node node, String name ){
    ArrayList<Node> r = new ArrayList<Node>();
    NodeList children = node.getChildNodes();
    int l = children.getLength();
    for( int i = 0; i < l; ++i ){
        if( name.equals( children.item(i).getNodeName() ) )
            r.add( children.item(i) );
    }
    return r;
}
È stato utile?

Soluzione

Questo perché quando si sta facendo parent.removeChild (nodo), genitore non è necessariamente il genitore del nodo perché getElementsByTagName () sta facendo una ricerca ricorsiva.

Altri suggerimenti

come su

nodeToBeRemoved.getParentNode().removeChild(nodeToBeRemoved);

parent.removeChild(node) sta gettando un NOT_FOUND_ERR perché node non è un bambino di parent. Vedo che node viene da getElementsByTagName che potrebbe non essere un figlio diretto di parent. Potrebbe essere ovunque sotto parent.

Sulla base della diagnosi @Maurice e @fahd ...

Non puoi semplicemente mettere una condizione prima di

parent.removeChild(node);

come

if (parent.isSameNode(node.getParentNode()))

Poi sarebbe rimuovere solo un figlio diretto del genitore data.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top