2012-12-04 21 views
40

Czy można odserializować nieznany XML do obiektu, jak poniżej?Deserializować XML do obiektu za pomocą Dynamic

var xml = @"<Students><Student><Name>Arul</Name><Mark>90</Mark></Student></Students>"; 

var serializer = new XmlSerializer(typeof(DynamicObject)); 

dynamic students = serializer.Deserialize(new XmlTextReader(new StringReader(xml))); 
+9

Dlaczego po prostu nie spróbować? –

+0

Próbowałem rzucić wyjątek, ale ta sama logika działa dla Json, dlaczego nie obsługuje z xml – user1875919

+0

Możliwy duplikat [Konwersja XML na dynamiczny obiekt C#] (https://stackoverflow.com/questions/13171525/converting-xml-to- a-dynamic-c-sharp-object) –

Odpowiedz

66

Możesz spróbować tego.

string xml = @"<Students> 
       <Student ID=""100""> 
        <Name>Arul</Name> 
        <Mark>90</Mark> 
       </Student> 
       <Student> 
        <Name>Arul2</Name> 
        <Mark>80</Mark> 
       </Student> 
      </Students>"; 

dynamic students = DynamicXml.Parse(xml); 

var id = students.Student[0].ID; 
var name1 = students.Student[1].Name; 

foreach(var std in students.Student) 
{ 
    Console.WriteLine(std.Mark); 
} 

public class DynamicXml : DynamicObject 
{ 
    XElement _root; 
    private DynamicXml(XElement root) 
    { 
     _root = root; 
    } 

    public static DynamicXml Parse(string xmlString) 
    { 
     return new DynamicXml(XDocument.Parse(xmlString).Root); 
    } 

    public static DynamicXml Load(string filename) 
    { 
     return new DynamicXml(XDocument.Load(filename).Root); 
    } 

    public override bool TryGetMember(GetMemberBinder binder, out object result) 
    { 
     result = null; 

     var att = _root.Attribute(binder.Name); 
     if (att != null) 
     { 
      result = att.Value; 
      return true; 
     } 

     var nodes = _root.Elements(binder.Name); 
     if (nodes.Count() > 1) 
     { 
      result = nodes.Select(n => n.HasElements ? (object)new DynamicXml(n) : n.Value).ToList(); 
      return true; 
     } 

     var node = _root.Element(binder.Name); 
     if (node != null) 
     { 
      result = node.HasElements || node.HasAttributes ? (object)new DynamicXml(node) : node.Value; 
      return true; 
     } 

     return true; 
    } 
} 
+4

Działa to świetnie, jeśli zwróconych jest wiele elementów przez niepowodzenie tylko jednego elementu, który jest zwracany i używasz go w foreach! Sugerowałbym zmianę "result = new DynamicXml (node);" do "result = new List () {new DynamicXml (node)};" która zwróci listę z jednym elementem. –

+0

Ustawianie lub pobieranie wartości atrybutów jest lepiej wykonywane przy pomocy TrySetIndex/TryGetIndex. Więc jeśli mamy element taki jak , składnia do osiągnięcia atrybutu name będzie osobą ["name"]. –

+1

@RezoMegrelidze Ale chciałem zaimplementować to jako 'person.name'. –