6

I have a struct more or less like this:

[Serializable]
[XmlRoot("Customer")]
public struct TCustomer
{
  string CustomerNo;
  string Name;
}

I sometimes serialize this this struct to XML as a single object, which works fine, but I also sometimes need to serialize a List<> of this struct.

I've used this to set the top level element name:

[Serializable]
[XmlRoot("Customers")]
public class CustomerList : List<TCustomer> { }

XmlSerializer however, insists on calling each list item TCustomer. How can I tell XmlSerializer to use the name Customer instead of TCustomer?

Thomas Kjørnes
  • 1,928
  • 1
  • 17
  • 17

5 Answers5

7

Hope it helps

[XmlType("Customer")]
[XmlRoot("Customer")]
public struct TCustomer
{
    public string CustomerNo;
    public string Name;
}
Anuraj
  • 18,859
  • 7
  • 53
  • 79
  • Nice! It would be nice if you could explain, though? – Ioannis Karadimas Feb 02 '11 at 13:44
  • Controls the XML schema that is generated when the attribute target is serialized by the XmlSerializer. - http://msdn.microsoft.com/en-us/library/system.xml.serialization.xmltypeattribute.aspx – Anuraj Feb 02 '11 at 13:50
  • This is more proper - Initializes a new instance of the XmlTypeAttribute class and specifies the name of the XML type. - http://msdn.microsoft.com/en-us/library/573s2dsz.aspx – Anuraj Feb 02 '11 at 13:51
  • +1 - I like this! I didn't know you could use XmlType in that way to control the name when used in a complex type (like `List`) – Adam Spicer Feb 02 '11 at 13:59
5

The XmlRoot attribute only applies for the root element, so it doesn't apply for TCustomer when you are serializing CustomerList.

Without implementing your own serialization, I don't think you can change TCustomer to serialize as Customer within the CustomerList class. But you can do something like this...

[Serializable]
[XmlRoot("customerList")]
public class CustomerList 
{
    [XmlArray("customers")]
    [XmlArrayItem("customer")]
    public List<TCustomer> Customers { get; set; }
}

That should give you xml similar to:

<customerList>
   <customers>
      <customer />
      <customer />
      <customer />
   </customers>
</customerList>

This changes your CustomerList from a generic list, but it allows you to control your naming.

Adam Spicer
  • 2,703
  • 25
  • 37
  • I have not yet seen a case where the accepted answer also works for serializing item names for standard types like `List MyList`, this answer however is flexible enough to handle renaming child tag names in that particular case. Also if you only need to rename the list element tags, I have noticed that only the `[XmlArrayItem("customer")]`is actually needed – Henrik Oct 07 '16 at 06:56
2

Thank's for all the answers. The sollution to my specific problem however, turned out to be as simple as:

[XmlRoot("Customers")]
public class Customers
{
    [XmlElement("Customer")]
    public List<TCustomer> List = new List<TCustomer>();
}
Thomas Kjørnes
  • 1,928
  • 1
  • 17
  • 17
1

I've never tried this at the class /struct level, but this is how I do it when I need to serialize a list inside a class.

    [XmlArray("ConfigurationList")]
    [XmlArrayItem("Configuration")]
    private List<string> pConfigList = new List<string>();
scott
  • 2,991
  • 5
  • 36
  • 47
0

You can implement IXmlSerializable in order to customize the way some object is serialized:

IXmlSerializable Interface

Anyway, it seems that serializer calls TCustomer the type of items because this is the actual type of the List (TCustomer is ???, where ??? will be the actual type of the generic parameter type TCustomer).

I wouldn't change the way XmlSerializer serializes objects without implementing IXmlSerializable (I mean, avoid a post-serializing text replacement or whatever!).

Mong Zhu
  • 23,309
  • 10
  • 44
  • 76
Matías Fidemraizer
  • 63,804
  • 18
  • 124
  • 206