Pregunta

Estoy construyendo un guión que tiene que parchear los archivos XML, incluyendo la sustitución de una lista de elementos con otros. La siguiente función se aplica un parche (que implica una lista posiblemente vacía de elementos con el mismo nombre) sobre la lista de elementos de un elemento padre por el mismo nombre (también posiblemente una lista vacía). (Esto es sólo una pequeña parte de la lógica de aplicación de parches).

¿Por qué, cuando corro el código, qué recibo el siguiente error?

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)

(línea 514 se etiqueta a continuación.) Por lo que yo entiendo, sólo he verificado que existe el elemento (NodeList porque es en vivo, su primera entrada siempre será el próximo partido o nulo). Curiosamente, esto no es siempre 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();
    }
}

Edit:. I utiliza la siguiente función como un reemplazo para getElementsByTagName() (ver respuesta aceptada)

/** 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;
}
¿Fue útil?

Solución

Esto es porque cuando usted está haciendo parent.removeChild (nodo), el padre no es necesariamente el padre del nodo debido getElementsByTagName () está haciendo una búsqueda recursiva.

Otros consejos

¿qué tal

nodeToBeRemoved.getParentNode().removeChild(nodeToBeRemoved);

parent.removeChild(node) es lanzar una NOT_FOUND_ERR porque node no es un niño de parent. Veo que viene de node getElementsByTagName que podría no ser un niño inmediata de parent. Podría ser en cualquier lugar bajo parent.

Sobre la base del diagnóstico por @Maurice y @fahd ...

¿No puedes poner una condición antes de

parent.removeChild(node);

como

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

Entonces sería solamente retirar a un niño directa de la matriz dada.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top