2013-05-15 35 views
9

Tôi có cấu trúc XML sau đây (được chỉnh sửa cho ngắn gọn) mà tôi không có quyền kiểm soát.Deserialize phần tử XML lồng vào lớp trong 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> 

Tôi có lớp sau:

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

Tôi muốn để có thể deserialize XML thành một trường hợp duy nhất của lớp Vehicle này. 99% thời gian, XML chỉ nên trả về một phần tử 'Xe'. Tôi chưa xử lý nó nếu nó chứa nhiều phần tử 'Xe' bên trong phần tử 'Xe'.

Thật không may, dữ liệu XML hiện không được ánh xạ tới thuộc tính lớp của tôi; chúng đang bị bỏ trống khi gọi phương thức Deserialize của tôi.

Để hoàn chỉnh, đây là phương pháp Deserialize của tôi:

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); 
    } 
} 

Tôi không quan tâm đến các yếu tố cha mẹ hơn khác như 'ApplicationArea', 'Lỗi' vv Tôi chỉ thú vị trong giải nén dữ liệu trong phần tử 'Xe'. Làm thế nào để tôi có được nó để chỉ deserialize dữ liệu này từ XML?

Trả lời

6

Tôi không biết bối cảnh đầy đủ của vấn đề của bạn, vì vậy giải pháp này có thể không phù hợp với miền của bạn. Nhưng có một giải pháp là để xác định mô hình của bạn như:

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

và vượt qua nút cụ thể vào Deserialize phương pháp sử dụng 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

Hoạt động tuyệt vời. Cảm ơn rất nhiều. – marcusstarnes

6

xây dựng trên Ilya của câu trả lời:

Điều này có thể được tối ưu hóa hơi , vì đã có một nút đã tải: không cần phải chuyển xml xuống một chuỗi (sử dụng vehicle.ToString()), chỉ để làm cho trình nối tiếp phải phân tích lại nó (sử dụng một StringReader).

Thay vào đó, chúng ta có thể tạo ra một độc giả trực tiếp sử dụng XNode.CreateReader:

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()); 
} 

Hoặc nếu dữ liệu là một XmlNode, sử dụng một 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); 
    } 
} 

Sau đó chúng tôi có thể sử dụng:

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

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

Lưu ý tuyệt vời, cảm ơn. –

+0

Có điều đó làm việc tốt cho tôi, và đã sử dụng XmlNode. Tuy nhiên, mã đã không hoạt động ngay lập tức. Tôi cần phải thay đổi mã trong việc sử dụng một chút để: xmlNodeReader.ReadStartElement(); return (T) ser.Deserialize (xmlNodeReader.ReadSubtree()); –

Các vấn đề liên quan