Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Allow duplicate node name in XML serialization using C#

Tags:

c#

xml

asp.net

I'm trying to serialize an object that have a duplicate node name using C#, the reason what i need to do this is because i'm building a library that use a third party API.

The request i need to build look like this.

<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>

My approach is create a class that represent the request and use the XML serialization attributes, the class look like this:

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

The base class of the attribute is:

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()
    {

    }
}

When i try to serialize and object i getting this error:

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.

Is there any work around to serialize this object or get the the structure of the request.

like image 604
dnlgmzddr Avatar asked Nov 05 '22 09:11

dnlgmzddr


1 Answers

What about using an array or list to de-serialize all <DATA>'s and then add properties which operate on this array?

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

I think you will also be able to come up with the setters.

like image 88
Krizz Avatar answered Nov 09 '22 04:11

Krizz