2013-07-15 31 views
8

Tôi có một số tệp XML với các phần tử gốc khác nhau, nhưng cùng loại phần tử con và tôi muốn có thể tạo một lớp duy nhất để giữ các phần tử gốc khác nhau để giữ mỗi phần tử con. Dưới đây là hai ví dụ về cách các tệp XML trông như thế nào.(De) tuần tự hóa các tên phần tử gốc khác nhau sử dụng một lớp

Tập 1:

<?xml version="1.0" encoding="utf-8" ?> 
<Sandra> 
    <Address> 
    <Street></Street> 
    <Number></Number> 
    </Address> 
</Sandra> 

Tập 2:

<?xml version="1.0" encoding="utf-8" ?> 
<John> 
    <Address> 
    <Street></Street> 
    <Number></Number> 
    </Address> 
</John> 

Tôi muốn để có thể cả serialize và deserialize này chỉ sử dụng 2 lớp, như:

[Serializable] 
[XmlRoot] 
public class Person 
{ 
    [XmlElement("Address")] 
    public List<Address> Adresses { get; set; } 
} 

[Serializable] 
public class Address 
{ 
    public string Street { get; set; } 

    public string Number { get; set; } 
} 

tôi cố đọc chúng bằng cách sử dụng:

var ser = new XmlSerializer(typeof(Person)); 
    var reader = XmlReader.Create("person1.xml"); 
    var person = (Person)ser.Deserialize(reader); 

Nhưng tôi nhận được "There is an error in XML document (2, 2).", bởi vì bộ khử mùi được mong đợi là một phần tử gốc <"Person"> và không phải là <"John"> hoặc <"Paul">. Nó hoạt động tốt nếu tôi thay đổi [XmlRoot] thành [XmlRoot("John")] nhưng đó là chính xác những gì tôi đang cố gắng tránh ở đây.

Ngoài ra, tôi phải có khả năng tuần tự hóa lại bằng cách sử dụng cùng cấu trúc XML lạ, vì vậy tôi cần lưu trữ tên phần tử gốc bên trong lớp Person.

Tôi biết tôi chỉ đơn giản có thể tạo bộ nối tiếp (de) của riêng mình nhưng tôi muốn biết liệu có thể đạt được nó bằng các phương pháp hiện có hay không.

Chỉnh sửa 1: (cuộn lại).

Chỉnh sửa 2: cuộn lại các sửa đổi "Chỉnh sửa 1" vì tôi đã tìm thấy cách đơn giản hơn để đạt được những gì tôi cần. Xem câu trả lời của tôi dưới đây.

Trả lời

8

Tìm thấy một cách gọn gàng và nhanh chóng để giải quyết vấn đề của tôi! Tôi chỉ cần sử dụng một XmlRootAttribute khi instantiating XmlSerializer. Bằng cách này tôi có thể đặt tên của phần tử gốc khi chạy.

var personsName = "Sandra"; 
var ser = new XmlSerializer(typeof(Person), 
    new XmlRootAttribute { ElementName = personsName }); 
var reader = XmlReader.Create("person1.xml"); 
var person = (Person)ser.Deserialize(reader); 

Tất nhiên nó cũng hoạt động theo cách tương tự nếu tôi muốn tuần tự hóa.

2

Sử dụng tên người làm tên phần tử XML cảm thấy hơi lạc quan. Mỗi phần tử đại diện cho một số John hoặc Person là gì?

Nó có thể là tốt hơn, nếu bạn có thể kiểm soát hình dạng của các tập tin XML, để đại diện cho họ như vậy:

<?xml version="1.0" encoding="utf-8" ?> 
<Person name="Sandra"> 
    <Address> 
    <Street></Street> 
    <Number></Number> 
    </Address> 
</Person> 

Và sau đó bạn sẽ có một cách dễ dàng để lưu trữ tên trong một tài sản, lập bản đồ như một thuộc tính XML:

[Serializable] 
[XmlRoot] 
public class Person 
{ 
    [XmlElement("Address")] 
    public List<Address> Adresses { get; set; } 

    [XmlAttribute("name")] 
    public string Name { get; set;} 
} 
+1

Yeah, nó kinda lạ, quả thật vậy. Nhưng không phải để tôi thay đổi cấu trúc XML, tôi chỉ phải đọc và viết tôn trọng định dạng này. –

1

thực hiện IXmlSerializable trong lớp học của bạn và làm tuần tự theo cách bạn muốn trong các chức năng:

ReadXml(System.Xml.XmlReader reader) và 012.

dụ:

[Serializable] 
public class Threshold : IXmlSerializable 
{ 

public int Type {get;set;} 
public object Value {get;set;} 
public string Name {get;set;} 
public void ReadXml(System.Xml.XmlReader reader) 
{ 


XElement thresholdXML = XElement.Load(reader); 

if (!thresholdXML.HasElements || thresholdXML.IsEmpty) 
return; 

Type = (ThresholdType)int.Parse(thresholdXML.Element("Type").Value); 
Value = Type.Equals(ThresholdType.Complex) ? thresholdXML.Element("Value").Value : (object)Decimal.Parse(thresholdXML.Element("Value").Value); 
Name = thresholdXML.Element("Name").Value; 


} 


public System.Xml.Schema.XmlSchema GetSchema() 
{ 
return null; 
} 

public void WriteXml(System.Xml.XmlWriter writer) 
{ 
XmlSerializerNamespaces xmlnsEmpty = new XmlSerializerNamespaces(); 
xmlnsEmpty.Add("", ""); 


writer.WriteElementString("Type", ((int)Type).ToString("D")); 
writer.WriteElementString("Value", Value.ToString()); 
writer.WriteElementString("Name", Name); 
} 
} 
+0

Tôi đã thử triển khai '' IXmlSerializable'' nhưng khi cố gắng Deserialize kho lưu trữ đầu tiên tôi nhận được lỗi tương tự '' {" không được mong đợi."} ''. Phương thức ReadXml() của classe thậm chí còn không được gọi. –

+0

Trước hết, bạn không cần bất kỳ thuộc tính [XmlRoot] hoặc [XmlElement] nào. Ngoài ra, hãy thử xóa XML hiện tại của bạn và tuần tự hóa các tệp mới. Đặt điểm ngắt trên ReadXML() và WriteXML() để xem chúng có được gọi hay không. Thực hiện theo các debbugger và cập nhật cho tôi với các chi tiết của trường hợp ngoại lệ và nơi nó xảy ra. –

+0

Đã làm những gì bạn nói với tôi để làm và có lỗi tương tự khi cố gắng deserialize nó: '' {" không được mong đợi."} ''. ReadXML vẫn không được gọi, có lẽ vì deserializer mong rằng tên lớp có cùng tên của phần tử gốc ** hoặc ** có thuộc tính '' [XmlRoot ("rootname")] ''. –

0

Sử dụng phần tử gốc làm ArrayOfClassName và sau đó thử.

<ArrayOfAlarmSummary> 
    <AlarmSummary> 
    <ClientId>1</ClientId> 
    <StationId>2</StationId> 
    <StationName>Station-2</StationName> 
    <DateTime>13/09/15</DateTime> 
    <TagName>AI2_2</TagName> 
    <Description>TR DC Current</Description> 
    <Units>Amps</Units> 
    <NormalOperation>10 to 100</NormalOperation> 
    <AlarmValue>132.48</AlarmValue> 
    <AlarmDescription> 
    </AlarmDescription> 
    </AlarmSummary> 
    <AlarmSummary> 
    <ClientId>1</ClientId> 
    <StationId>2</StationId> 
    <StationName>Station-2</StationName> 
    <DateTime>13/09/15</DateTime> 
    <TagName>AI2_2</TagName> 
    <Description>TR AC Current</Description> 
    <Units>Amps</Units> 
    <NormalOperation>10 to 100</NormalOperation> 
    <AlarmValue>132.48</AlarmValue> 
    <AlarmDescription> 
    </AlarmDescription> 
    </AlarmSummary> 
</ArrayOfAlarmSummary> 

Đây là lớp deserialize, sử dụng bạn có thể deserialize tệp Xml của bạn.

public class SerializeDeserialize<T> 
    { 
     StringBuilder sbData; 
     StringWriter swWriter; 
     XmlDocument xDoc; 
     XmlNodeReader xNodeReader; 
     XmlSerializer xmlSerializer; 
     public SerializeDeserialize() 
     { 
      sbData = new StringBuilder(); 
     } 
     public string SerializeData(T data) 
     { 
      XmlSerializer employeeSerializer = new XmlSerializer(typeof(T)); 
      swWriter = new StringWriter(sbData); 
      employeeSerializer.Serialize(swWriter, data); 
      return sbData.ToString(); 
     } 

     public T DeserializeData(string dataXML) 
     { 
      xDoc = new XmlDocument(); 
      xDoc.LoadXml(dataXML); 
      xNodeReader = new XmlNodeReader(xDoc.DocumentElement); 
      xmlSerializer = new XmlSerializer(typeof(T)); 
      var employeeData = xmlSerializer.Deserialize(xNodeReader); 
      T deserializedEmployee = (T)employeeData; 
      return deserializedEmployee; 
     } 
    } 

Gọi lớp

var appDomain = System.IO.Directory.GetCurrentDirectory() + "\\AlarmFiles"; 
      var strPath = Path.Combine(appDomain, 
       "Alarm_" + DateTime.Now.ToString("ddMMyyyy") + Constants.FileType.XmlFile); 
      var fi = new FileInfo(strPath); 
      if (fi.Exists) 
      { 
       try 
       { 
        var xmlString = System.IO.File.ReadAllText(strPath); 
        var serializeAlarmSummary = 
         new SerializeDeserialize<List<AlarmSummary>>(); 
        return serializeAlarmSummary.DeserializeData(xmlString); 
       } 
       catch (Exception ex) 
       { 
        throw ex; 
       } 

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