18

要素のリストを別のリストに置き換えるなど、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

4 に答える 4

15

どうですか

nodeToBeRemoved.getParentNode().removeChild(nodeToBeRemoved);
于 2013-09-25T20:41:23.990 に答える
14

これは、parent.removeChild(node) を実行している場合、getElementsByTagName() が再帰検索を実行しているため、必ずしも親がノードの親であるとは限らないためです。

于 2010-09-15T16:28:24.503 に答える
4

parent.removeChild(node)nodeはの子ではないため、NOT_FOUND_ERR をスローしていparentます。の直接の子ではない可能性があることnodeから来ていることがわかりました。の下のどこかにある可能性があります。getElementsByTagNameparentparent

于 2010-09-15T17:02:37.573 に答える
0

@Mauriceと@fahdによる診断に基づいて...

前に条件を付けることはできません

parent.removeChild(node);

そのような

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

次に、指定された親の直接の子のみを削除します。

于 2010-09-15T21:43:04.600 に答える