Abbruch foreach Schleife



  • Hallo.

    Ich will aus einem XML Dokument leere Knoten löschen. Speziell die eines bestimmten Root Knoten.

    Der Code dazu mal etwas zusammengefasst

    XmlDocument xdDocument = new XmlDocument();
    xdDocument.Load(Page.MapPath("App_Data/BlackBoard.xml"));
    XmlElement xeRootNode = xdDocument.DocumentElement;
    XmlNodeList xnlList = xeRootNode.ChildNodes;
    
    foreach (XmlNode xnNode in xnlList)
    {
        if (xnNode.ChildNodes.Count == 0)
        {
            xnNode.ParentNode.RemoveChild(xnNode);
        }
    }
    xdDocument.Save(Page.MapPath("App_Data/BlackBoard.xml"));
    

    Mein Problem ist, dass die foreach Schleife sofort abbricht, wenn das erste mal

    xnNode.ParentNode.RemoveChild(xnNode);
    

    aufgerufen wird, obwohl noch mehrere Knoten vorhanden sind. Wenn ich diese Zeile auskommentiere, läuft er wie gewünscht alle Knoten durch (dann ohne Effekt). Ich kann es auch irgendwie nachvollziehen, da ich ja direkt etwas ändere, was ich aktuell parse.
    Wie löst man denn sowas?



  • Also kenn mich mit XML nicht so gut aus, aber wenn ich Deinen Code richtig interpretiere gehst Du alle Kinder des root-Knoten durch und sobald ein Kind dieser Kinder Count==0 hat, löscht Du den root-Knoten, also auch alle restlichen Kinder.
    Du hattest Doch auch geschrieben, du wolltest den root-Knoten löschen...

    Kann es sein, dass Du nur einen Zweig löschen willst?

    Dann müsstest Du es wohl eher so schreiben:

    xnNode.Remove()
    

    Wobei ich nicht weiss, ob der Befehl so existiert, weil ich mich wie gesagt nciht auskenne, aber von der Idee her müsstest Du das aktuelle Objekt löschen, welches du in der Schleife behandelst...



  • Wie kommst du darauf, dass ich den Root Knoten lösche?
    Und ich hab auch nicht geschrieben, dass ich den Root Knoten löschen will.

    Ich hole mir eine Liste aller Knoten aus xeRootNode. Dann gehe ich diese Liste durch und wenn dort ein leerer Knoten bei ist, gehe ich zum übergeordneten Knoten (xeRootNode) und lösche diesen leeren Knoten (xnNode).
    Das funktioniert auch, aber nur einmal, da dann die foreach Schleife frühzeitig abbricht.



  • oneill5000 schrieb:

    Mein Problem ist, dass die foreach Schleife sofort abbricht, wenn das erste mal

    xnNode.ParentNode.RemoveChild(xnNode);
    

    aufgerufen wird, obwohl noch mehrere Knoten vorhanden sind.

    es bricht nichts willkürlich ab ... Du verschluckst irgendwo eine Exception - etwa so

    try
    {
      // foo()
    } catch(exception ex) { }
    

    ansonsten kannst Du nicht einfach die Enumeration ändern wärend Du durchläufst - und genau diese Exception wird da geworfen ... sammle einfach die zu entfernen Elemente in einer anderen Liste und schmeiß sie anschließend raus

    hand, mogel



  • Das alles beifindet sich im original in einem try catch Block. Es wird keine exception geworfen.



  • sorry, hattezu flüchtig drüber gelesen.

    Benutz mal ein Delegate um die aus der Liste zu löschen wg. der Enumeration.



  • Ich habe irgendwie noch keine Ansatz. Wie soll ich die Knoten denn sammeln?

    Zur Info, die xml Datei könnte so aussehen

    <?xml version="1.0" encoding="utf-8"?>
    <entries>
        <entry>
        </entry>
        <entry>
        </entry>
        <entry>
            <header>test</header>
            <content>test</content>
            <entrydate>20100205</entrydate>
            <deletedate>20100206</deletedate>
            <user>Max</user>
        </entry>
    </entries>
    

    Dort sollen jetzt

    <entry>
        </entry>
        <entry>
        </entry>
    

    gelöscht werden.



  • Du hast ja eine Node Liste. Wenn sie Ilist eingebunden hat, sollte folgendes funktionieren:

    list.RemoveAll(delegate(string s) { return s == "irgendweineBedingung"; });
    

    Müsstest Du dann noch auf Dein Problem anpassen, also vermutlich in der Art:

    list.RemoveAll(delegate(XmlNode n) { return n == (xnNode.ChildNodes.Count == 0) ; });
    

    Hoffe das funktioniert so...



  • Hmm. Nein, sowas gibt es nicht für eine XmlNodeList.



  • Holzhammermethode:

    XmlDocument document = new XmlDocument();
    document.Load(@"..\..\test.xml");
    XmlNode entriesNode = document.SelectSingleNode("entries");
    XmlNodeList entryNodes = entriesNode.SelectNodes("entry");
    List<XmlNode> entryNodesToDelete = new List<XmlNode>();
    foreach (XmlNode entryNode in entryNodes)
    {
    	XmlElement entryElement = entryNode as XmlElement;
    	if (entryElement != null)
    	{
    		if (entryElement.ChildNodes.Count == 0)
    		{
    			entryNodesToDelete.Add(entryElement);
    		}
    	}
    }
    foreach (XmlNode entryNode in entryNodesToDelete)
    {
    	entriesNode.RemoveChild(entryNode);
    }
    document.Save(@"..\..\test_new.xml");
    


  • Du kannst auch über LINQ To XML rangehen und löschen.



  • @theta

    Danke, so funktioniert es.


Anmelden zum Antworten