Je construis un script qui doit corriger des fichiers XML, y compris en remplaçant une liste d'éléments par une autre. La fonction suivante applique un patch (impliquant une liste éventuellement vide d'éléments portant le même nom) sur la liste d'éléments d'un élément parent du même nom (éventuellement une liste vide). (Ceci est seulement une petite partie de la logique de correction). Pourquoi, lorsque j'exécute le code, j'obtiens l'erreur suivante?Pourquoi ne puis-je pas supprimer un élément enfant que je viens de trouver? NOT_FOUND_ERR
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'utilisé 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;
}
Merci tous les deux. Y at-il une version non récursive - 'getChildNodes()' et implémenter ma propre recherche par nom peut-être? Plus j'apprends sur la bibliothèque XML de Java, moins je trouve qu'elle fait ce que je m'attendais. – dhardy
Je suppose que vous devrez mettre en œuvre votre propre recherche –
Cela semblait être la meilleure solution. J'ai implémenté une fonction retournant 'List' puisque dans mon cas je ne veux pas non plus du comportement" live "de' NodeList' (ajouté à la fin de ma question puisque je ne peux pas poster de blocs de code ici). –
dhardy