¿Por qué no puedo eliminar un elemento secundario que acabo de descubrir? NOT_FOUND_ERR
-
03-10-2019 - |
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;
}
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.