为什么我不能删除我刚发现的子元素? NOT_FOUND_ERR

我正在构建一个必须修补XML文件的脚本,包括用另一个元素替换一个元素列表。 以下函数将补丁(包含可能为空的同名元素列表)应用于父元素的同名元素列表(也可能是空列表)。 (这只是修补逻辑的一小部分)。

为什么,当我运行代码时,是否会出现以下错误?

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) 

(第514行标记如下。)据我所知,我刚刚validation了该元素是否存在(因为NodeList是实时的,它的第一个条目将始终是下一个匹配或null)。 有趣的是,这并不总是一个问题。

 private static class PTReplaceNodeList extends PTBase { private final String name; private final String nextElement; private final List 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(); } } 

编辑:我使用以下函数替代getElementsByTagName() (请参阅接受的答案)。

 /** Returns all direct children of node with name name. * * Note: not the same as getElementsByTagName(), which finds all descendants. */ static List getChildNodes( Node node, String name ){ ArrayList r = new ArrayList(); 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; } 

这是因为当您执行parent.removeChild(node)时,parent不一定是节点的父节点,因为getElementsByTagName()正在执行递归搜索。

怎么样

 nodeToBeRemoved.getParentNode().removeChild(nodeToBeRemoved); 

parent.removeChild(node)正在抛出NOT_FOUND_ERR,因为node不是parent的子parent 。 我看到该node来自getElementsByTagName ,它可能不是parent node的直接子parent 。 它可能在parent任何地方。

在@Maurice和@fahd诊断的基础上……

你不能只是提出一个条件

 parent.removeChild(node); 

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

然后它只会移除给定父级的直接子级。