I have a class containing an array I wish to serialize with XmlSerializer:
[XmlArray("properties")]
[XmlArrayItem("property", IsNullable = true)]
public List<Property> Properties { get; set; }
Property is a class containing an attribute and some XmlText:
[XmlAttribute("name")]
public string Name { get; set; }
[XmlText]
public string Value { get; set; }
The problem is that when Value is null, it serializes as an empty string:
<property name="foo" />
rather than a null. I'm looking for the value to either be omitted entirely, or look like this:
<property name="foo" xsi:nil="true" />
Is it possible to null out an element in a list based on its XmlText value?  I'm really trying to avoid custom serialization, but perhaps some other serialization framework would be better in this case?
Use the IsNullable=true in the XmlArrayItemAttribute class. For an example.
[XmlRoot("Root")]
public class Root
{
    [XmlArrayItem("Element", IsNullable = true)]
    public string[] Elements { get; set; }
}
Some sample code in Visual Studion 2012 and .Net 4.5:
using System.Xml.Serialization;
...
// Test object
Root root;
root = new Root();
root.Elements = new string[] { null, "abc" };
using(MemoryStream stream = new MemoryStream())
{
    XmlSerializer xmlSerializer = new XmlSerializer(typeof(Root));
    xmlSerializer.Serialize(stream, root);
    Console.WriteLine(new string(Encoding.UTF8.GetChars(stream.GetBuffer())));
}
The output is (line breaks added for clarity):
<?xml version="1.0"?>
<Root 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Element>
    <string xsi:nil="true" />
    <string>abc</string>
  </Element>
</Root>
And with a complex type (also in .Net 4.5 on Visual Studio 2012):
    public class MyProperty
    {
        public string Foo { get; set; }
    }
    [XmlRoot("Root")]
    public class Root
    {
        [XmlArrayItem("Element", IsNullable = true)]
        public MyProperty[] Elements { get; set; }
    }
    ,,,
    Root root;
    root = new Root();
    root.Elements = new MyProperty[] { null, new MyProperty{ Foo = "bar" } };
    // Other code is as above
Using the same code above produces:
<?xml version="1.0"?>
<Root 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Elements>
    <Element xsi:nil="true" />
    <Element>
      <Foo>bar</Foo>
    </Element>
  </Elements>
</Root>
Also remember that the type must be a reference type (not a struct, for example) to write out xsi:nil=true.
One thought - you could use "NameSpecified", but check the value of "Value" in the get. Meaning, if Value is null, then Name will not be output either.
Unfortunately, you will still have a null property xml element, tho; I hope that's more acceptable...
class Program
{
    static void Main(string[] args)
    {
        ObjectWithProperties obj = new ObjectWithProperties()
        {
            Properties = new List<Property>()
        };
        Property p = new Property();
        p.Name = "This WILL Show Up";
        p.Value = "I'm here";
        obj.Properties.Add(p);
        Property p1 = new Property();
        p1.Name = "This Will NOT Show Up";
        obj.Properties.Add(p1);
        Console.WriteLine(ToXmlString(obj));
        Console.ReadLine();
    }
    public static string ToXmlString(object value)
    {
        if (value == null) return string.Empty;
        XmlSerializer ser = new XmlSerializer(value.GetType());
        MemoryStream ms = new MemoryStream();
        ser.Serialize(ms, value);
        return Encoding.UTF8.GetString(ms.ToArray());
    }
}
public class ObjectWithProperties
{
    [XmlArray("properties")]
    [XmlArrayItem("property", IsNullable = true)]
    public List<Property> Properties { get; set; }
}
public class Property
{
    [XmlAttribute("name")]
    public string Name { get; set; }
    [XmlIgnore]
    public bool NameSpecified
    {
        get { return !string.IsNullOrEmpty(Value); }
    }
    [XmlText]
    public string Value { get; set; }
}
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With