2013-05-15 8 views
9

Ich habe die folgende XML-Struktur (zur Kürze bearbeitet), die ich nicht kontrollieren kann.Deserialisieren geschachtelten XML-Element in Klasse in C#

<GetVehicles> 
    <ApplicationArea> 
     <Sender> 
      <Blah></Blah> 
     </Sender> 
    </ApplicationArea> 
    <DataArea> 
     <Error> 
      <Blah></Blah> 
     </Error> 
     <Vehicles> 
      <Vehicle> 
       <Colour>Blue</Colour> 
       <NumOfDoors>3</NumOfDoors> 
       <BodyStyle>Hatchback</BodyStyle> 
      <Vehicle> 
     </Vehicles> 
    </DataArea> 
</GetVehicles> 

Ich habe die folgende Klasse:

[XmlRoot("GetVehicles"), XmlType("Vehicle")] 
public class Vehicle 
{ 
    public string Colour { get; set; } 
    public string NumOfDoors { get; set; } 
    public string BodyStyle { get; set; } 
} 

Ich möchte die XML-Daten in einer einzigen Instanz dieser Fahrzeugklasse deserialisieren können. In 99% der Fälle sollte der XML-Code nur ein einziges "Vehicle" -Element zurückgeben. Ich bin noch nicht damit beschäftigt, wenn es mehrere "Vehicle" -Elemente im Element "Vehicles" enthält.

Leider werden die XML-Daten derzeit nicht meinen Klasseneigenschaften zugeordnet. Sie werden beim Aufruf meiner Deserialize-Methode leer gelassen.

Für Vollständigkeit, hier ist meine Deserialize Methode:

private static T Deserialize<T>(string data) where T : class, new() 
{ 
    if (string.IsNullOrEmpty(data)) 
     return null; 

    var ser = new XmlSerializer(typeof(T)); 

    using (var sr = new StringReader(data)) 
    { 
     return (T)ser.Deserialize(sr); 
    } 
} 

I usw. nicht über die anderen mehr übergeordneten Elemente wie ‚Application‘, ‚Fehler‘ kümmern bin ich nur interessant, in die Daten zu extrahieren innerhalb des Elements 'Fahrzeug'. Wie bekomme ich es, diese Daten nur aus dem XML-Code zu deserialisieren?

Antwort

6

Mir ist der vollständige Kontext Ihres Problems nicht bekannt, daher passt diese Lösung möglicherweise nicht in Ihre Domäne. Aber eine Lösung ist Ihr Modell zu definieren, wie:

[XmlRoot("Vehicle")] //<-- optional 
public class Vehicle 
{ 
    public string Colour { get; set; } 
    public string NumOfDoors { get; set; } 
    public string BodyStyle { get; set; } 
} 

und passiert bestimmte Knoten in Deserialize Methode LINQ to XML:

var vehicle = XDocument.Parse(xml) 
         .Descendants("Vehicle") 
         .First(); 

Vehicle v = Deserialize<Vehicle>(vehicle.ToString()); 


//display contents of v 
Console.WriteLine(v.BodyStyle); //prints Hatchback 
Console.WriteLine(v.Colour);  //prints Blue 
Console.WriteLine(v.NumOfDoors); //prints 3 
+0

Funktioniert gut. Danke vielmals. – marcusstarnes

6

Aufbauend auf Ilyas Antwort:

Diese leicht optimiert werden kann Da es bereits einen geladenen Knoten gibt: Es ist nicht notwendig, das XML in eine Zeichenkette herunter zu geben (unter Verwendung von vehicle.ToString()), nur um zu veranlassen, dass der Serialisierer es erneut analysieren muss (unter Verwendung einer StringReader).

Stattdessen können wir erstellt einen Leser direkt XNode.CreateReader mit:

private static T Deserialize<T>(XNode data) where T : class, new() 
{ 
    if (data == null) 
     return null; 

    var ser = new XmlSerializer(typeof(T)); 
    return (T)ser.Deserialize(data.CreateReader()); 
} 

Oder wenn Daten ein XmlNode ist, verwenden Sie ein XmlNodeReader:

private static T Deserialize<T>(XmlNode data) where T : class, new() 
{ 
    if (data == null) 
     return null; 

    var ser = new XmlSerializer(typeof(T)); 
    using (var xmlNodeReader = new XmlNodeReader(data)) 
    { 
     return (T)ser.Deserialize(xmlNodeReader); 
    } 
} 

Wir können dann verwenden:

var vehicle = XDocument.Parse(xml) 
         .Descendants("Vehicle") 
         .First(); 

Vehicle v = Deserialize<Vehicle>(vehicle); 
+0

Tolle Nachricht, danke. –

+0

Ja, das hat gut für mich funktioniert und XmlNode verwendet. Der Code funktionierte jedoch nicht sofort. Ich musste den Code in der Verwendung leicht ändern, um: xmlNodeReader.ReadStartElement(); Rückgabe (T) ser.Deserialize (xmlNodeReader.ReadSubtree()); –

Verwandte Themen