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

时间:2010-09-15 15:46:02

标签: java xml removechild getelementsbytagname

我正在构建一个必须修补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行标记如下。)据我所知,我刚刚验证了该元素是否存在(因为NodeList是实时的,它的第一个条目将始终是下一个匹配或null)。有趣的是,这并不总是一个问题。

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();
    }
}

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

/** 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;
}

4 个答案:

答案 0 :(得分:13)

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

答案 1 :(得分:12)

怎么样

nodeToBeRemoved.getParentNode().removeChild(nodeToBeRemoved);

答案 2 :(得分:4)

parent.removeChild(node)正在抛出NOT_FOUND_ERR,因为node不是parent的孩子。我发现node来自getElementsByTagNameparent可能不是parent的直接孩子。它可以在{{1}}下的任何地方。

答案 3 :(得分:0)

以@Maurice和@fahd的诊断为基础......

你能不能在

之前提出一个条件
parent.removeChild(node);

,例如

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

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