Estoy construyendo una secuencia de comandos que tiene que parchear archivos XML, incluida la sustitución de una lista de elementos por otra. La siguiente función aplica un parche (que involucra una lista posiblemente vacía de elementos con el mismo nombre) en la lista de elementos de un elemento padre con el mismo nombre (posiblemente también una lista vacía). (Esto es solo una pequeña parte de la lógica de parchado).¿Por qué no puedo eliminar un elemento secundario que acabo de encontrar? NOT_FOUND_ERR
¿Por qué, cuando ejecuto el código, obtengo 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 siempre es 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: 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;
}
Gracias a los dos. ¿Hay alguna versión no recursiva, 'getChildNodes()' e implementar mi propia búsqueda por nombre, tal vez? Cuanto más estoy aprendiendo acerca de la biblioteca XML de Java, menos estoy descubriendo que hace lo que esperaba. – dhardy
Supongo que tendrá que implementar su propia búsqueda –
Esta parece ser la mejor solución. Implementé una función devolviendo 'List' ya que en mi caso tampoco quiero realmente el comportamiento "en vivo" de 'NodeList' (agregado al final de mi pregunta ya que no puedo publicar bloques de código aquí). –
dhardy