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

Controlling Serialization of XML Elements

When serializing classes to XML, each public property and field value is transformed into an XML element. The name of the element matches the name of the property. The XmlElement attribute allows the names and formatting of XML tags to be modified.

Specifying Derived Types in Collections

The Type parameter can also be used with collections. To demonstrate, first change the data initialisation code as follows. This creates a department with Bob as the contact. Bob now has two subordinates, one a team leader and one an employee.

Employee sam = new Employee();
sam.Name = "Sam";

TeamLeader mel = new TeamLeader();
mel.Name = "Mel";

TeamLeader bob = new TeamLeader();
bob.Name = "Bob";
bob.Subordinates = new ArrayList();
bob.Subordinates.Add(sam);
bob.Subordinates.Add(mel);

Department dept = new Department();
dept.Name = "IT";
dept.Budget = 250000M;XMLElement_3.aspx
dept.Contact = bob;

We can serialize the Department object without specifying the data types for the collection. The results are shown below. Note that the items in the collection are in anyType elements. The data type in each case is specified in an XML attribute. This output is often unsatisfactory.

<Department>
    <Name>IT</Name> 
    <Budget>250000</Budget> 
    <TeamLeader>
        <Name>Bob</Name> 
        <Subordinates>
        <anyType xsi:type="Employee">
            <Name>Sam</Name> 
        </anyType>
        <anyType xsi:type="TeamLeader">
            <Name>Mel</Name> 
        </anyType>
        </Subordinates>
    </TeamLeader>
</Department>

To remove the anyType elements, we need to specify the types that can be found in the collection. To tell the serializer to expect either Employees or TeamLeaders, modify the TeamLeader class as follows:

public class TeamLeader : Employee
{
    [XmlElement(Type = typeof(Employee))]
    [XmlElement(Type = typeof(TeamLeader))]
    public ArrayList Subordinates { get; set; }
}

Re-running the serialization changes the anyType elements to the more readable names of the data types.

<Department>
    <Name>IT</Name> 
    <Budget>250000</Budget> 
    <TeamLeader>
        <Name>Bob</Name> 
        <Employee>
            <Name>Sam</Name> 
        </Employee>
        <TeamLeader>
            <Name>Mel</Name> 
        </TeamLeader>
    </TeamLeader>
</Department>

When declaring the permitted types, you can also specify the element name for each type using the ElementName parameter. For example, the modified TeamLeader class below changes TeamLeaders to SubteamLeaders and Employees to Grunts.

public class TeamLeader : Employee
{
    [XmlElement(ElementName = "Grunt", Type = typeof(Employee))]
    [XmlElement(ElementName = "SubteamLeader", Type = typeof(TeamLeader))]
    public ArrayList Subordinates { get; set; }
}

Run the program again to see the results:

<Department>
    <Name>IT</Name> 
    <Budget>250000</Budget> 
    <TeamLeader>
        <Name>Bob</Name> 
        <Grunt>
            <Name>Sam</Name> 
        </Grunt>
        <SubteamLeader>
            <Name>Mel</Name> 
        </SubteamLeader>
    </TeamLeader>
</Department>

Using the xsi:nil Attribute

The last parameter that we will consider in this article is IsNullable. By default, when you serialize a property or field that has a null value, no XML element is created. We can see this by simplifying the initialisation of the department variable as follows:

Department dept = new Department();
dept.Budget = 250000M;

When serialized, the resultant XML is similar to that shown below. Note that the Name element is not present.

<Department>
    <Budget>250000</Budget> 
</Department>

An alternative to excluding an element is to include it and explicitly state that it has no value. This is achieved by including the xsi:nil attribute in the XML element. To instruct the serializer to use this format, set the IsNullable parameter of the XmlElement attribute to true:

public class Department
{
    [XmlElement(IsNullable=true)]
    public string Name { get; set; }

    public decimal Budget { get; set; }

    [XmlElement(Type = typeof(Employee))]
    [XmlElement(Type = typeof(TeamLeader))]
    public Employee Contact { get; set; }
}

Serializing the modified object gives the following results. Note that the Name element is now present with the xsi:nil attribute set to true.

<Department>
    <Name xsi:nil="true" /> 
    <Budget>250000</Budget> 
</Department>
25 January 2011