# Problem beim löschen von ChildNodes aus einem XML-DOM



## binärbär (12. Nov 2009)

Hallo!

Ich versuche mich nun schon ewig im löschen von einigen Child-Knoten aus einem XML Dokument. Ich verwende als DOM das "org.w3c.dom.Document" und nutze den Standard Parser (nicht JDOM).

hier mal die XML Struktur:
[XML]
<root>
	<node status="status">
	<node_A>Name A</node_A>
	<node_B>Beschreibung</node_B>
	<node_C>Ein Text</node_C>
	<node_D>Irgendwas...</node_D>
	<subNode status="status">
		<subA>text</subA>
		<subB>text</subB>
		<subC>text</subC>
	</subNode>
	<subNode status="status">
		<subA>text</subA>
		<subB>text</subB>
		<subC>text</subC>
	</subNode>
	<subNode status="status">
		<subA>text</subA>
		<subB>text</subB>
		<subC>text</subC>
	</subNode>
	</node>
	<node status="status">
	<node_A>Name B</node_A>
	<node_B>Beschreibung</node_B>
	<node_C>Ein Text</node_C>
	<node_D>Irgendwas...</node_D>
	<subNode status="status">
		<subA>text</subA>
		<subB>text</subB>
		<subC>text</subC>
	</subNode>
	<subNode status="status">
		<subA>text</subA>
		<subB>text</subB>
		<subC>text</subC>
	</subNode>
	<subNode status="status">
		<subA>text</subA>
		<subB>text</subB>
		<subC>text</subC>
	</subNode>
	</node>
</root>
[/XML]

Ich möchte z.B. alle SubNodes löschen, die zum Element "<node status="status">" gehören und diese wiederum die Untermenge von "Name B" vom Element <node_A> sind. 
Und genau da liegt mein Problem... ich bekomme die Subnodes zu einem bestimmten übergeordneten Knoten nicht vollständig gelöscht. :autsch:

Mein Quelltext bisher:

```
Element root = document.getDocumentElement();
Element parent;
NodeList nl = root.getElementsByTagName("node_A");
    for (int i = 0; i < nl.getLength(); i++) {
        Element e = (Element)nl.item(i);
		//alle subNodes vom Knoten "Name B" sollen gelöscht werden 
        if(e.getTextContent().equals("Name B")){
            parent = (Element)e.getParentNode();
            NodeList nl1 = parent.getElementsByTagName("subNode");
            for (int j = 0; j < nl1.getLength(); j++) {
					Element el = (Element)nl1.item(j);
                    if(null != el && el.hasChildNodes()){
							parent = (Element)el.getParentNode();
							parent.removeChild(el);
                    }
            }
        }
    }
```

Wenn ich die Childs so versuche zu löschen, werden zwar ein paar Childs entfernt aber es bleiben immer noch welche übrig???:L

Hat vielleicht jemand eine Idee, wie ich dies bewerkstelligen kann??

Vielen Dank!

PS: Hier mal ein Ausschnitt zum testen:

```
import java.io.File;
import java.io.IOException;
import java.io.OutputStreamWriter;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.xml.sax.SAXException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;


public class ParserTestClass {
    private Document document;
    private String datei        = "C:\\Temp\\XML-Datei.xml";

    public ParserTestClass(){
        try {
            File file = new File(datei);

            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            factory.setValidating(false); //erzeugt ein nicht validiertes Document
            DocumentBuilder docBuilder = factory.newDocumentBuilder();
            document = docBuilder.parse(file);
        } catch (SAXException ex) {
            ex.printStackTrace();

        } catch (IOException ex) {
            ex.printStackTrace();
        } catch (ParserConfigurationException ex) {
            ex.printStackTrace();
        }

    }
    public void printDOM(){
        //TransformerFactory erzeugen
        TransformerFactory tf = TransformerFactory.newInstance();

        //Einrückungstiefe definieren
        tf.setAttribute("indent-number", new Integer(3));
        Transformer t = null;
        try {
            //eine neue Transformer Instanz erzeugen
            t = tf.newTransformer();

            //Parameter setzen: Einrücken
            t.setOutputProperty(OutputKeys.INDENT, "yes");
            //Ausgabe-Typ: XML
            t.setOutputProperty(OutputKeys.METHOD, "xml");
            //Content-Type
            t.setOutputProperty(OutputKeys.MEDIA_TYPE, "text/xml");

         // Transformation durchführen und Ergebnis in einen Stream speichern
         t.transform(new DOMSource(document),
            new StreamResult(
               new OutputStreamWriter(System.out)));

        } catch (TransformerConfigurationException ex) {
            ex.printStackTrace();
        } catch (TransformerException ex) {
            ex.printStackTrace();
        }

    }

    public void deleteSubNodes(String nodeValue) {
        //TODO das löschen funktioniert noch nicht...
        Element root = document.getDocumentElement();
        Element parent;
        NodeList nl = root.getElementsByTagName("node_A");
        for (int i = 0; i < nl.getLength(); i++) {
            Element e = (Element)nl.item(i);
            if(e.getTextContent().equals(nodeValue)){
                parent = (Element)e.getParentNode();
                NodeList nl1 = parent.getElementsByTagName("subNode");
                for (int j = 0; j < nl1.getLength(); j++) {
                        Element el = (Element)nl1.item(j);
                        if(null != el && el.hasChildNodes()){
                            parent = (Element)el.getParentNode();
                            parent.removeChild(el);
                        }
                    }

                return;
            }
        }
    }
        /**
    * @param args the command line arguments
    */
    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                ParserTestClass myClass = new ParserTestClass();
                myClass.printDOM();
                System.out.println("------------------------------");
                myClass.deleteSubNodes("Name B");
                myClass.printDOM();

            }
        });
    }

}
```


----------



## dagmar (12. Nov 2009)

Hi,
ich habe zwar noch nie DOM direkt verwendet, was mir aber in Deinem Code aufgefallen ist: Warum biegst Du in der letzten Schleife den parent noch mal um? 


binärbär hat gesagt.:


> ```
> parent = (Element)el.getParentNode();
> ```


Du hast den korrekten Parent schon oben in der Hand. Vielleicht hat das ja einen Effekt?
Gruß
dagmar


----------



## binärbär (12. Nov 2009)

Hi Dagmar,

ich habe das mal wieder ausgeklammert und es mit dem parent aus der ersten Schleife versucht, was leider genau den selben Effekt hat, dass teilweise die Childs gelöscht werden und andere noch erhalten bleiben...

Also noch mal zum veranschaulichen:
[Java]
            for (int j = 0; j < nl1.getLength(); j++) {
                    Element el = (Element)nl1.item(j);
                    if(null != el && el.hasChildNodes()){
                            //parent = (Element)el.getParentNode();
                            parent.removeChild(el);
                    }
[/Java]

Das komische ist, in der NodeList ist genau die Anzahl der Elemente vorhanden, die ich auch tatsächlich löschen möchte, nur ist ein Teil davon NULL... deshalb hab ich noch die prüfung auf NULL mit in der Abfrage... es kommt sonst zur NullPointerEx.


----------



## binärbär (12. Nov 2009)

Ok, nach langem rumprobieren hab ich nun die Lösung gefunden... ich war schon nahe dran...
Also, wen es noch interessieren sollte:
Die NodeList wird dynamisch angepasst also muss ich die Schleife etwas abändern...

```
Element root = document.getDocumentElement();
Element parent;
NodeList nl = root.getElementsByTagName("node_A");
    for (int i = 0; i < nl.getLength(); i++) {
        Element e = (Element)nl.item(i);
        //alle subNodes vom Knoten "Name B" sollen gelöscht werden 
        if(e.getTextContent().equals("Name B")){
            parent = (Element)e.getParentNode();
            NodeList nl1 = parent.getElementsByTagName("subNode");
//Hier der geänderte Abschnitt:
                while ( nl1.getLength()>0) {
                        Element el = (Element)nl1.item(0);
                        parent.removeChild(el);
                }
            }
        }
    }
```


----------

