2012-06-15 10 views
7

Dieser ist ein wenig schwierig. Sagen wir, ich habe diese XmlDocumentSo entfernen Sie alle leeren XElements

<Object> 
    <Property1>1</Property1> 
    <Property2>2</Property2> 
    <SubObject> 
     <DeeplyNestedObject /> 
    </SubObject> 
</Object> 

ich diese zurück Da jedes der Kinder <SubObject>

<Object> 
    <Property1>1</Property1> 
    <Property2>2</Property2> 
</Object> 

erhalten möchten alle leeren Elemente ich es loswerden wollen. Die Herausforderung besteht darin, dass Sie Knoten nicht entfernen können, während Sie über sie hinweg iterieren. Jede Hilfe würde sehr geschätzt werden.

UPDATE Hier ist, was ich mit aufgewickelt.

public XDocument Process() 
{ 
    //Load my XDocument 
    var xmlDoc = GetObjectXml(_source); 

    //Keep track of empty elements 
    var childrenToDelete = new List<XElement>(); 

    //Recursively iterate through each child node 
    foreach (var node in xmlDoc.Root.Elements()) 
     Process(node, childrenToDelete); 

    //An items marked for deletion can safely be removed here 
    //Since we're not iterating over the source elements collection 
    foreach (var deletion in childrenToDelete) 
     deletion.Remove(); 

    return xmlDoc; 
} 

private void Process(XElement node, List<XElement> elementsToDelete) 
{ 
    //Walk the child elements 
    if (node.HasElements) 
    { 
     //This is the collection of child elements to be deleted 
     //for this particular node 
     var childrenToDelete = new List<XElement>(); 

     //Recursively iterate each child 
     foreach (var child in node.Elements()) 
      Process(child, childrenToDelete); 

     //Delete all children that were marked as empty 
     foreach (var deletion in childrenToDelete) 
      deletion.Remove(); 

     //Since we just removed all this nodes empty children 
     //delete it if there's nothing left 
     if (node.IsEmpty) 
      elementsToDelete.Add(node); 
    } 

    //The current leaf node is empty so mark it for deletion 
    else if (node.IsEmpty) 
     elementsToDelete.Add(node); 
} 

Wenn jemand in dem Anwendungsfall dafür interessiert ist, ist es für ein ObjectFilter Projekt, das ich zusammen.

+0

Verwenden Sie die System.Xml zum Lesen der Konfigurationsdatei –

+4

@sarooptrivedi: Lesen Sie die Frage. – SLaks

+0

@SLaks: Ich mache die gleichen Dinge in meinem Projekt. Sie können das XMLDOcument lesen und dann die Datei aktualisieren und das XML zuletzt speichern –

Antwort

9

Es wird ziemlich langsam sein, aber man kann dies tun:

XElement xml; 
while (true) { 
    var empties = xml.Descendants().Where(x => x.IsEmpty && !x.HasAttributes).ToList(); 
    if (empties.Count == 0) 
     break; 

    empties.ForEach(e => e.Remove()); 
} 

, um es schneller zu machen, können Sie die übergeordneten Knoten nach der ersten Iteration gehen und sehen, ob sie leer sind.

XElement xml; 
var empties = xml.Descendants().Where(x => x.IsEmpty && !x.HasAttributes).ToList(); 
while (empties.Count > 0) { 
    var parents = empties.Select(e => e.Parent) 
         .Where(e => e != null) 
         .Distinct() //In case we have two empty siblings, don't try to remove the parent twice 
         .ToList(); 

    empties.ForEach(e => e.Remove()); 

    //Filter the parent nodes to the ones that just became empty. 
    parents.RemoveAll(e => e.IsEmpty && !e.HasAttributes); 
    empties = parents; 
} 
+0

Danke für die Hilfe! – Micah

+0

Ich hatte das gleiche Problem und diese Lösung entfernt nur einige der Elemente, leere String-Werte lassen. Diese Änderung half: 'var leer = xml.Descendants(). Wobei (x => (x.IsEmpty || string.IsNullOrEmpty (x.Value)) &&! X.HasAttributes) .ToList();' – user5226582

-1

Hier erstelle ich eine XML-Datei, in der ich den gesamten XML-Code. Sie können auch die XmlLoad("") zum Laden der XML verwenden. Dies funktioniert mit dem Laden von Dateien. Sie können auch mit XmlLoad versuchen.

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Xml; 

namespace Test 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      XmlDocument doc = new XmlDocument(); 
      doc.Load("Test.xml"); 
      XmlElement root = doc.DocumentElement; 
      foreach (var item in root) 
      { 
       XmlElement elem = (XmlElement)item; 
       if (elem.InnerText.Equals("")) 
       { 
        foreach (var child in elem.ChildNodes) 
        { 
         XmlElement childelem = (XmlElement)child; 
         childelem.RemoveAll(); 
        } 

        elem.ParentNode.RemoveChild(elem); 
       } 
      } 
      doc.Save("Test.xml"); 
      Console.ReadLine(); 
     } 
    } 
} 
Verwandte Themen