Michael Shaw Michael Shaw - 2 months ago 13
C# Question

Avoiding using the “http://www.w3.org/2001/XMLSchema-instance” namespace with .Net DataContractSerializer

I have a series of classes that I am converting to XML using .NET's DataContractSerializer in .NET 4.0. The serialisation is working fine, and I can parse the XML and recreate the .NET objects later without any difficulty.

However, most of the DataMember's are not required. [DataMember(IsRequired = false)]. This works great on de-serializing the XML, where you can then just miss the XML node out of the document, but when serializing an exisiting object into XML, the DataContractSerializer insists on writing out properties that have null values as nodes with an attribute e.g.

[DataContract(Name = "response", Namespace = "http://domain.com/name")]
public class MyResponseClass
{
[DataMember(Name = "count", IsRequired = true, Order = 0)]
public int Count { get; set; }

[DataMember(Name = "info", IsRequired = false, Order = 1)]
public InfoClass Info { get; set; }

[DataMember(Name = "metadata", IsRequired = false, Order = 2)]
public MetadataList Metadatas { get; set; }

}


can be serialised from

<response xmlns="http://domain.com/name">
<count>4</count>
</response>


However, if I serialise the object, it creates:

<response xmlns="http://domain.com/name" xmlns:i="http://www.w3.org/2001/XmlSchema-instance">
<count>4</count>
<info i:nil="true" />
<metadata i:nil="true" />
</response>


Is there any way to get the DataContractSerializer to not write the node instead, when it has a null value?

Answer

Use EmitDefaultValue = false to skip default values in XML:

[DataContract(Name = "response", Namespace = "http://domain.com/name")]
public class MyResponseClass 
{
    [DataMember(Name = "count", IsRequired = true, Order = 0, EmitDefaultValue = false)]
    public int Count { get; set; }

    [DataMember(Name = "info", IsRequired = false, Order = 1, EmitDefaultValue = false)]
    public InfoClass Info { get; set; }

    [DataMember(Name = "metadata", IsRequired = false, Order = 2, EmitDefaultValue = false)]
    public MetadataList Metadatas { get; set; }
}

to remove xmlns:i="http://www.w3.org/2001/XmlSchema-instance" you have to use for example Replace() like in the following example

public void Write(string filePath, MyResponseClass myResponse)
{
    var serializer = new DataContractSerializer(typeof(MyResponseClass));

    var sb = new StringBuilder();
    using (var writer = new StringWriter(sb))
    using (var xmlWriter = XmlWriter.Create(writer))
    {
        serializer.WriteObject(xmlWriter, myResponse);
    }

    using (StreamWriter stream = new StreamWriter(filePath))
    {
        sb = sb.Replace(" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\"", "");
        stream.Write(sb);
    }
}

with regards :)