18

I have an xml in which one of the elements has an attribute that can be blank. For e.g.,

<tests>
<test language="">
.....
</test>
</tests>

Now, language is enum type in the classes created from the schema. It works fine if the language is specified, it fails to deserialize if it is blank (as shown in example).

Edit: Code for deserialization:

XmlSerializer xmlserializer = new XmlSerializer(type);
StringReader strreader = new StringReader(stringXML);
Object o = serializer.Deserialize(strreader);

How can I handle this scenario

abatishchev
  • 98,240
  • 88
  • 296
  • 433
genericuser
  • 1,430
  • 4
  • 22
  • 40

5 Answers5

21

You could declare the enum property as nullable:

public Language? Language { get; set; }


EDIT: ok, I just tried, it doesn't work for attributes... Here's another option: don't serialize/deserialize this property directly, but serialize a string property instead :

[XmlIgnore]
public Language Language { get; set; }

[XmlAttribute("Language")]
public string LanguageAsString
{
    get { return Language.ToString(); }
    set
    {
        if (string.IsNullOrEmpty(value))
        {
            Language = default(Language);
        }
        else
        {
            Language = (Language)Enum.Parse(typeof(Language), value);
        }
    }
}
Thomas Levesque
  • 286,951
  • 70
  • 623
  • 758
  • That also means you can store a null value there, which is bad encapsulation IMHO. It's better to provide a non-nullable in this case, and convert to a defeault value on the setter. – Camilo Martin Nov 22 '10 at 22:31
  • 2
    This is not the best way as you adapt your model to the technology, and that is not a good thing. – Vajda Aug 29 '11 at 15:56
  • @Vajda, I know it's not ideal... if you have a better solution, I'll be glad to hear it. – Thomas Levesque Aug 29 '11 at 21:47
  • 1
    @Thomas Levesque, Here is the best way to do this. Just look the example code. http://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlenumattribute.aspx – Vajda Aug 30 '11 at 08:10
  • @Vajda, I agree it's cleaner, but it's not quite the same... it will always serialize the default value as an empty string, which might not be the desired effect. – Thomas Levesque Aug 30 '11 at 08:20
  • @Thomas Levesque, I posted answer below. So you can see. – Vajda Aug 30 '11 at 14:36
  • You also need to consider @Mike Hofer example below (XmlEnumAttribute) which will cause the Enum.Parse to fail. And a value like "2" would get parsed to the enum value matching 2 rather than the one matching the XmlEnumAttribute("2") (as another interesting way to fail) – Roger Willcocks Nov 18 '16 at 10:19
  • @ThomasLevesque Hi Thomas, could you please help me ? I've posted a new 'answer' to the question because I didn't know how to ask you within a comment and including all the code. Please see my answer below. Thanks ! – Roger Apr 12 '19 at 15:28
  • I like this answer for deserializing enums that cannot have the XmlEnum attribute. For example: SqlDbType – Jon Koeter Sep 30 '20 at 09:15
19

You probably need to mark up your enumeration, and add a default item that represents Unknown.

For example:

Public Enum EmployeeStatus
   <XmlEnum("")> Unknown = 0
   <XmlEnum("Single")> One = 1
   <XmlEnum("Double")> Two = 2
   <XmlEnum("Triple")> Three = 3
End Enum

For more information, see here.

PseudoNinja
  • 2,846
  • 1
  • 27
  • 37
Mike Hofer
  • 16,477
  • 11
  • 74
  • 110
18

You can do it this way:

namespace Example
{

   public enum Language
   {
     [XmlEnum("en")]
     English,

     [XmlEnum("de")]
     Deutsch
   }

   public class ExampleClass
   {

      private Language? language;

      [XmlAttribute("Language")]
      public Language Language
      {
         get { return language ?? Example.Language.English; }
         set { language = value; }
      }

      .
      .
      .
   }
}
Vajda
  • 1,795
  • 6
  • 39
  • 49
2

What would you want the result to be ?

A blank value cannot be mapped to a null reference since an enum is a non-nullable value type.

GuiSim
  • 7,361
  • 6
  • 40
  • 50
0
object wontBeNull = couldBeNull ?? defaultIfNull;

Is what I'd try. It's called Null-Coalescing operator, I use it when I want a default for null input.

Flot2011
  • 4,601
  • 3
  • 44
  • 61
Camilo Martin
  • 37,236
  • 20
  • 111
  • 154
  • I am not sure how to implement this. I have a property of the enum type, which should deserialized. How do I mention this in the property when I declare it??? – genericuser Nov 22 '10 at 22:34
  • Seriously though, have you considered a try-catch block? If you put one around your deserialization, it can catch many errors and malformed XML files. – Camilo Martin Nov 22 '10 at 22:43