views:

1516

answers:

4

I have a a property defined as:

[XmlArray("delete", IsNullable = true)]
[XmlArrayItem("contact", typeof(ContactEvent)),
 XmlArrayItem("sms", typeof(SmsEvent))]
public List<Event> Delete { get; set; }

If the List<> Delete has no items

<delete />

is emitted. If the List<> Delete is set to null

<delete xsi:nil="true" />

is emitted. Is there away using attributes to get the delete element not to be emitted if the collection has no items?

Greg - Perfect thanks, I didn't even read the IsNullable documentation just assumed it was signalling it as not required.

Rob Cooper - I was trying to avoid ISerializable, but Gregs suggestion works. I did run into the problem you outlined in (1), I broke a bunch of code by just returning null if the collection was zero length. To get around this I created a EventsBuilder class (the class I am serializing is called Events) that managed all the lifetime/creation of the underlying objects of the Events class that spits our Events classes for serialization.

A: 

You could always implement IXmlSerializer and perform the serialization manually.

See http://www.codeproject.com/KB/cs/IXmlSerializable.aspx for an example.

Craig Eddy
+3  A: 

If you set IsNullable=false or just remove it (it is false by default), then the "delete" element will not be emitted. This will work only if the collection equals to null.

My guess is that there is a confusion between "nullability" in terms of .NET, and the one related to nullable elements in XML -- those that are marked by xml:nil attribute. XmlArrayAttribute.IsNullable property controls the latter.

Greg
This doesn't answer the question? "is there away using attributes to get the delete element not to be emitted if the collection has no items?" This is basically what the asker has now?
Rob Cooper
+1  A: 

First off, I would say ask yourself "What is Serialization?".

The XmlSerializer is doing exactly what it is supposed to be doing, persisting the current state of the object to XML. Now, I am not sure why the current behaviour is not "right" for you, since if you have initialized the List, then it is initialized.

I think you have three options here:

  1. Add code to the Getter to return null if the collection has 0 items. This may mess up other code you have though.
  2. Implement the IXmlSerializable interface and do all the work yourself.
  3. If this is a common process, then you may want to look at my question "XML Serialization and Inherited Types" - Yes, I know it deals with another issue, but it shows you how to create a generic intermediary serialization class that can then be "bolted on" to allow a serilization process to be encapsulated. You could create a similar class to deal with overriding the default process for null/zero-item collections.

I hope this helps.

Rob Cooper
+4  A: 

I've had the same issue where I did not want an element outputted if the field is empty or 0. The XML outputted could not use xsi:null="true" (by design).

I've read somewhere that if you include a property of type bool with the same name as the field you want to control but appended with 'Specified', the XMLSerializer will check the return value of this property to determine if the corresponding field should be included.

To achieve this without implementing IXMLSerializer:

public List<Event> Delete { get; set; }
[XMLIgnore]
public bool DeleteSpecified
{
 get
 {
   bool isRendered = false;
   if (Delete != null)
   {
     isRendered = (Delete.Count > 0);
   } 

   return isRendered;
 }
 set
 {
 }
}
theahuramazda