2011-12-13 25 views
5

Tôi đang cố gắng để serialize một đối tượng mà có một tên nút trùng lặp sử dụng C#, lý do gì tôi cần phải làm điều này là bởi vì tôi đang xây dựng một thư viện mà sử dụng một bên thứ ba API.Cho phép tên nút trùng lặp trong serialization XML bằng C#

Yêu cầu tôi cần xây dựng trông như thế này.

<DATASET> 
    <SITE_ID>123</SITE_ID> 
    <DATA type=“name”>Secondary List</DATA> 
    <DATA type="extra" id="CLICKTHRU_URL">http://my.domain.com/</DATA> 
    <DATA type="extra" id="REPLY_FORWARD_EMAIL">[email protected]</DATA> 
    <DATA type="extra" id="REPLY_FROM_EMAIL">[email protected]</DATA> 
    <DATA type="extra" id="REPLY_FROM_NAME">[email protected]</DATA> 
    <DATA type="extra" id="REPLY_FORWARD_SUBJECT">Customer Replies</DATA> 
    <DATA type="extra" id="HANDLE_UNSUBSCRIBE"></DATA> 
    <DATA type="extra" id="HANDLE_AUTOREPLY"></DATA> 
    <DATA type="extra" id="FOOTER_TEXT">Confidentiality agreement…</DATA> 
    <DATA type="extra" id="FOOTER_HTML"> Confidentiality agreement…</DATA> 
</DATASET> 

cách tiếp cận của tôi là tạo ra một lớp đại diện cho yêu cầu và sử dụng các thuộc tính XML serialization, giao diện lớp như thế này:

[XmlRoot("DataSet")] 
public class AddListCallHolder : BaseCallHolder 
{ 
    private BaseAttributeHolder _name = new BaseAttributeHolder(type: ""); 

    [XmlElement("DATA")] 
    public BaseAttributeHolder Name 
    { 
     get { return _name; } 
     set { _name = value; } 
    } 

    private BaseAttributeHolder _clickthruUrl = new BaseAttributeHolder(id: "CLICKTHRU_URL"); 

    [XmlElement("DATA")] 
    public BaseAttributeHolder CLICKTHRU_URL 
    { 
     get { return _clickthruUrl; } 
     set { _clickthruUrl = value; } 
    } 
} 

Các lớp cơ sở của thuộc tính là:

public class BaseAttributeHolder 
{ 
    [XmlAttribute("type")] 
    public string Type { get; set; } 

    [XmlAttribute("id")] 
    public string Id { get; set; } 

    [XmlText] 
    public string Value { get; set; } 

    public BaseAttributeHolder(string value, string id, string type = "extra") 
    { 
     Type = type; 
     Value = value; 
     Id = id; 
    } 

    public BaseAttributeHolder(string id, string type = "extra") 
    { 
     Type = type; 
     Id = id; 
    } 

    public BaseAttributeHolder(string type = "extra") 
    { 
     Type = type; 
    } 

    public BaseAttributeHolder() 
    { 

    } 
} 

Khi tôi cố gắng sắp xếp và đối tượng tôi gặp phải lỗi này:

The XML element 'DATA' from namespace '' is already present in the current scope. Use XML attributes to specify another XML name or namespace for the element.

Có bất kỳ công việc xung quanh để sắp đặt từng hàng đối tượng này hoặc nhận cấu trúc của yêu cầu.

+0

+1 cho một câu hỏi đầu tiên thực sự cũng hỏi –

Trả lời

2

gì về việc sử dụng một mảng hoặc danh sách để de-serialize tất cả <DATA> 's và sau đó thêm các thuộc tính mà hoạt động trên mảng này?

[XmlRoot("DataSet")] 
    public class AddListCallHolder 
    { 
     [XmlArrayItem(typeof(BaseAttributeHolder), ElementName = "DATA")] 
     public BaseAttributeHolder[] data 
     { 
      get; 
      set; 
     } 

     [XmlIgnore] 
     public BaseAttributeHolder Name 
     { 
      get 
      { 
      return data.FirstOrDefault(d => d.Type == "name"); 
      } 
     } 

     [XmlIgnore] 
     public BaseAttributeHolder CLICKTHRU_URL 
     { 
      get 
      { 
      return data.FirstOrDefault(d => d.Type == "extra" && d.Id == "CLICKTHRU_URL"); 
      } 
     } 
    } 

Tôi nghĩ bạn cũng sẽ có thể tìm ra những người định cư.

+0

1 để giữ cho các thuộc tính. – dash

+0

Cảm ơn bạn, giải pháp sạch sẽ. Cảm ơn tất cả các bạn vì câu trả lời nhanh và giải thích. – dnlgmzddr

0

Bạn không thể thực sự thực hiện việc này mà không tự tùy chỉnh việc tuần tự hóa; vấn đề là nó serializer cần phải xác định duy nhất các thuộc tính serialized trong đầu ra. Nếu tất cả chúng đều có tên "DATA" thì nó không thể thực sự làm được điều này.

gì bạn có thể làm thay thế là:

[XmlType(TypeName="Data")] 
public class BaseAttributeHolder 
{ 
    [XmlAttribute("type")] 
    public string Type { get; set; } 

    [XmlAttribute("id")] 
    public string Id { get; set; } 

    [XmlText] 
    public string Value { get; set; } 


    public BaseAttributeHolder(string value, string id, string type = "extra") 
    { 
     Type = type; 
     Value = value; 
     Id = id; 
    } 

    public BaseAttributeHolder(string id, string type = "extra") 
    { 
     Type = type; 
     Id = id; 
    } 

    public BaseAttributeHolder(string type = "extra") 
    { 
     Type = type; 
    } 

    public BaseAttributeHolder() 
    { 

    } 
} 

[XmlRoot("DataSet")] 
public class AddListCallHolder 
{ 
    [XmlElement("SITE_ID")] 
    public string Site =""; 

    private BaseAttributeHolder _name = new BaseAttributeHolder(type: ""); 

    [XmlElement("DATA")] 
    public List<BaseAttributeHolder> Attributes { get; set; } 


    public AddListCallHolder() 
    { 
     Attributes = new List<BaseAttributeHolder>(); 
     Attributes.Add(new BaseAttributeHolder(id: "CLICKTHRU_URL")); 
     Attributes.Add(new BaseAttributeHolder()); 

    } 


} 

Vì vậy, lớp AddCallHolder của bạn sẽ phơi bày nó thuộc tính như một danh sách các thuộc tính.

Nếu bạn sau đó serialize trên:

AddListCallHolder callHolder = new AddListCallHolder(); 

    XmlSerializer ser = new XmlSerializer(typeof(AddListCallHolder)); 

    StringBuilder sb = new StringBuilder(); 

    TextWriter writer = new StringWriter(sb); 

    ser.Serialize(writer, callHolder); 

    sb.ToString(); 

bạn sẽ nhận được:

<?xml version="1.0" encoding="utf-16"?> 
    <DataSet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
      <SITE_ID /> 
      <Data type="extra" id="CLICKTHRU_URL" /> 
      <Data /> 
    </DataSet> 

Đó là khoảng cách duy nhất để làm điều đó (mà không cần viết phương pháp serialization của riêng bạn mà là tốt nhưng rõ ràng là làm việc nhiều hơn).

EDIT:

Tôi thực sự như giải pháp Krizz khi anh giữ các thuộc tính ban đầu về lớp học của bạn, bằng cách sử dụng mảng như một container cho serialization, và thuộc tính XmlIgnore như vậy mà serializer bỏ qua các tài sản trên serialization/deserialization. Các thuộc tính vừa trở thành mảng tra cứu/chèn trên mảng.

0
[XmlRoot("DATASET")] 
public class DS 
{ 
    [XmlElement("SITE_ID")] 
    public string Site =""; 

    [XmlElement("DATA")] 
    public Data[] Data = null; 

} 

[XmlRoot("DATA")] 
public class Data 
{ 
    [XmlAttribute("type")] 
    public string Type =""; 

    [XmlAttribute("id")] 
    public string Id = null; 

    [XmlText] 
    public string Text = ""; 
} 

XmlSerializer xs = new XmlSerializer(typeof(DS)); 
var obj = xs.Deserialize(new MemoryStream(Encoding.UTF8.GetBytes(xmlstring))); 

MemoryStream m = new MemoryStream(); 
xs.Serialize(m,obj); 
MessageBox.Show(Encoding.UTF8.GetString(m.ToArray())); 

và đây là xmlstring bạn

string xmlstring = 
    @" 
<DATASET> 
    <SITE_ID>123</SITE_ID> 
    <DATA type=""name"">Secondary List</DATA> 
    <DATA type=""extra"" id=""CLICKTHRU_URL"">http://my.domain.com/</DATA> 
    <DATA type=""extra"" id=""REPLY_FORWARD_EMAIL"">[email protected]</DATA> 
    <DATA type=""extra"" id=""REPLY_FROM_EMAIL"">[email protected]</DATA> 
    <DATA type=""extra"" id=""REPLY_FROM_NAME"">[email protected]</DATA> 
    <DATA type=""extra"" id=""REPLY_FORWARD_SUBJECT"">Customer Replies</DATA> 
    <DATA type=""extra"" id=""HANDLE_UNSUBSCRIBE""></DATA> 
    <DATA type=""extra"" id=""HANDLE_AUTOREPLY""></DATA> 
    <DATA type=""extra"" id=""FOOTER_TEXT"">Confidentiality agreement…</DATA> 
    <DATA type=""extra"" id=""FOOTER_HTML""> Confidentiality agreement…</DATA> 
</DATASET> 
"; 
Các vấn đề liên quan