BlackWaspTM

This web site uses cookies. By using the site you accept the cookie policy.This message is for compliance with the UK ICO law.

XML
.NET 2.0+

XML Serialization of Arrays and Collections

Arrays and collections can be serialized to XML. The standard action when using the default serializer is for the name of the collection property to be added to the XML, with a contained element for each item named according to the items' data types.

XmlArrayItem

The XmlArrayItem attribute is used to modify the inner elements that each represent an item from the collection. If you wish to use a custom name for the elements instead of the data type, you can provide it in a similar manner as with XmlArray. In the following updated Department class the attribute specifies that the inner elements should be named, "StaffMember". The XmlArray attribute is also present.

public class Department
{
    public string Name { get; set; }

    [XmlArray("Staff")]
    [XmlArrayItem("StaffMember")]
    public List<Employee> Employees { get; set; }

    public Department()
    {
        Employees = new List<Employee>();
    }
}

The resultant XML is as follows:

<Department>
  <Name>IT</Name>
  <Staff>
    <StaffMember>
      <Name>Bob</Name>
    </StaffMember>
    <StaffMember>
      <Name>Jim</Name>
    </StaffMember>
    <StaffMember>
      <Name>Mel</Name>
    </StaffMember>
  </Staff>
</Department>

Named Parameters

If you want to modify other behaviour, you must use named parameters within the XmlArray and XmlArrayItem attributes. The following sections describe some of the more commonly used named parameters.

Changing Element Names

The previous examples used a basic form for both attributes to modify the names of elements. You can achieve the same results using the ElementName parameter. To demonstrate, try running the serialization for the modified class below. Here the element names are modified using the named parameter. The results are identical to the previous example:

public class Department
{
    public string Name { get; set; }

    [XmlArray(ElementName = "Staff")]
    [XmlArrayItem(ElementName = "StaffMember")]
    public List<Employee> Employees { get; set; }

    public Department()
    {
        Employees = new List<Employee>();
    }
}

Setting Namespaces

In some situations you may need to modify the namespaces of the serialized items. You can do this with the Namespace parameter. In the XmlArray attribute this changes the namespace of the outer element. With XmlArrayItem, the namespace is applied to each inner element.

The following Department class changes the namespace for both attributes, each having a different value:

public class Department
{
    public string Name { get; set; }

    [XmlArray(ElementName = "Staff", Namespace="http://www.blackwasp.co.uk")]
    [XmlArrayItem(ElementName = "StaffMember",
        Namespace = "http://www.blackwasp.co.uk/Staff")]
    public List<Employee> Employees { get; set; }

    public Department()
    {
        Employees = new List<Employee>();
    }
}

You can see the results below.

<Department>
  <Name>IT</Name>
  <Staff xmlns="http://www.blackwasp.co.uk">
    <StaffMember xmlns="http://www.blackwasp.co.uk/Staff">
      <Name>Bob</Name>
    </StaffMember>
    <StaffMember xmlns="http://www.blackwasp.co.uk/Staff">
      <Name>Jim</Name>
    </StaffMember>
    <StaffMember xmlns="http://www.blackwasp.co.uk/Staff">
      <Name>Mel</Name>
    </StaffMember>
  </Staff>
</Department>

Specifying Derived Types

The final named parameter that we will consider is Type. This is only available for the XmlArrayItem attribute. When you are serializing an array or a collection that can contain several different types, generally in an inheritance relationship, you can use the Type attribute to specify the different types in the array that may be serialized or to adjust the XML generation for each type.

You should provide one XmlArrayItem attribute for each of the data types that may exist within the list. You can also specify other named parameters, which may vary by type. This is demonstrated in the updated Department class shown below. Here we have two types that may be serialized. If an item is of the Employee type, the generated XML element will be named, "StaffMember". If the employee is of the derived type, "Manager", the default name will be used. The name must be different for each data type to ensure that the XML can be deserialized correctly later.

public class Department
{
    public string Name { get; set; }

    [XmlArray(ElementName = "Staff", Namespace="http://www.blackwasp.co.uk")]
    [XmlArrayItem(ElementName = "StaffMember", Type = typeof(Employee))]
    [XmlArrayItem(Type = typeof(Manager))]
    public List<Employee> Employees { get; set; }

    public Department()
    {
        Employees = new List<Employee>();
    }
}
10 July 2011