Question

Je construis un script qui doit patcher des fichiers XML, y compris le remplacement d'une liste d'éléments avec un autre. La fonction suivante applique un patch (impliquant une liste éventuellement vide d'éléments avec le même nom) sur une liste des parents Élément d'éléments par le même nom (éventuellement une liste vide). (Ceci est seulement une petite partie de la logique de correction).

Pourquoi, quand je lance le code, puis-je obtenir l'erreur suivante?

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)

(ligne 514 est étiqueté ci-dessous.) Pour autant que je le comprends, je viens vérifié que l'élément existe (car NodeList est en direct, sa première entrée sera toujours le prochain match ou nul). Fait intéressant, ce n'est pas toujours un problème.

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:. J'utilise la fonction suivante en remplacement de getElementsByTagName() (voir réponse acceptée)

/** 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;
}
Était-ce utile?

La solution

En effet, lorsque vous faites parent.removeChild (noeud), parent est pas nécessairement le parent du nœud parce getElementsByTagName () fait une recherche récursive.

Autres conseils

Que diriez-vous

nodeToBeRemoved.getParentNode().removeChild(nodeToBeRemoved);

parent.removeChild(node) est de lancer un NOT_FOUND_ERR parce node est pas un enfant de parent. Je vois que node vient de getElementsByTagName qui pourrait ne pas être un enfant immédiat de parent. Il pourrait être partout sous parent.

Miser sur le diagnostic par @Maurice et @fahd ...

ne peut pas vous mettre juste un état avant

parent.removeChild(node);

comme

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

Alors il ne supprime un enfant direct du parent donné.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top