2013-04-10 12 views

risposta

25

Per una soluzione veramente efficace:

e.IsEmpty = true; 

è la vostra opzione più veloce e più semplice. Fa esattamente ciò che hai richiesto: tutto il testo interno e gli elementi nidificati vengono scartati, mentre gli attributi vengono mantenuti.

+0

Questa è la soluzione che stavo aspettando! Ho verificato con Reflector che questa proprietà fa esattamente ciò che è richiesto. – usr

4

Opzione 1 Uso elem.InnerXml = ""; Il codice di lavoro pieno, se avete bisogno di questo:

var doc = new XmlDocument(); 
    doc.LoadXml("<x a1='a' a2='b'><child1/><child2/></x>"); 
    var elem = doc.DocumentElement; 

    Console.WriteLine(elem.OuterXml); 
    Console.WriteLine("HasAttributes " + elem.HasAttributes); 
    Console.WriteLine("HasChildNodes " + elem.HasChildNodes); 

    elem.InnerXml = ""; 
    Console.WriteLine(elem.OuterXml); 
    Console.WriteLine("HasAttributes " + elem.HasAttributes); 
    Console.WriteLine("HasChildNodes " + elem.HasChildNodes); 
    Console.ReadLine(); 

Detailied informazioni che cosa InnerXml fare:

public override string InnerXml 
    { 
     get 
     { 
     return base.InnerXml; 
     } 
     set 
     { 
     this.RemoveAllChildren(); 
     new XmlLoader().LoadInnerXmlElement(this, value); 
     } 
    } 

Ci potrebbe essere problema di prestazioni sul LoadInnerXmlElement ma perché noi avere una stringa vuota non dovrebbe essere grande, perché la maggior parte del tempo impiegherà questo metodo:

internal XmlNamespaceManager ParsePartialContent(XmlNode parentNode, string innerxmltext, XmlNodeType nt) 
    { 
     this.doc = parentNode.OwnerDocument; 
     XmlParserContext context = this.GetContext(parentNode); 
     this.reader = this.CreateInnerXmlReader(innerxmltext, nt, context, this.doc); 
     try 
     { 
     this.preserveWhitespace = true; 
     bool isLoading = this.doc.IsLoading; 
     this.doc.IsLoading = true; 
     if (nt == XmlNodeType.Entity) 
     { 
      XmlNode newChild; 
      while (this.reader.Read() && (newChild = this.LoadNodeDirect()) != null) 
      parentNode.AppendChildForLoad(newChild, this.doc); 
     } 
     else 
     { 
      XmlNode newChild; 
      while (this.reader.Read() && (newChild = this.LoadNode(true)) != null) 
      parentNode.AppendChildForLoad(newChild, this.doc); 
     } 
     this.doc.IsLoading = isLoading; 
     } 
     finally 
     { 
     this.reader.Close(); 
     } 
     return context.NamespaceManager; 
    } 

Opzione 2 seguente codice:

XmlNode todelete = elem.FirstChild; 
    while (todelete != null) 
    { 
     elem.RemoveChild(elem.FirstChild); 
     todelete = elem.FirstChild; 
    } 

Chi performane. Vediamo in XmlElement.RemoveAll() è:

public override void RemoveAll() 
{ 
    base.RemoveAll(); 
    this.RemoveAllAttributes(); 
} 

Dove base.RemoveAll() è esattamente:

[TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")] 
public virtual void RemoveAll() 
{ 
    XmlNode oldChild = this.FirstChild; 
    for (; oldChild != null; { 
    XmlNode nextSibling; 
    oldChild = nextSibling; 
    } 
) 
    { 
    nextSibling = oldChild.NextSibling; 
    this.RemoveChild(oldChild); 
    } 
} 

Quindi è lo stesso come ho scritto sopra Sarebbe questa soluzione non

+1

Avrei delle riserve sulle prestazioni per questo. Sembra anche hacky. Mi piacerebbe trattare con il documento XML su un livello AST, non a livello di stringa. – usr

+0

Ho aggiunto spiegazione dettagliata –

+0

Ok, grazie! Metterò questo in un metodo di estensione e il problema è ora risolto bene per tutte le volte. – usr

4

essere più semplice?

while(e.FirstChild != null) 
    e.RemoveChild(e.FirstChild); 
+0

Questo è un po 'quello che ho fatto. Ho copiato cosa fa XmlNode.RemoveAll. – usr

Problemi correlati