1

Consider an element like this:

<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="XMLSchema1" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="Foo">
    <xs:complexType>
      <xs:attribute name="MyList">
        <xs:simpleType>
          <xs:list itemType="xs:int" />
        </xs:simpleType>
      </xs:attribute>
    </xs:complexType>
  </xs:element>
</xs:schema>

E.g.:

<Foo MyList='1 2 3' />

This corresponds to this C# class:

[Serializable]
public class Foo
{
  [XmlAttribute]
  public int[] MyList { get; set; }
}

And that’s (basically) what xsd.exe /classes generates.

Serializing and Deserializing works great, except deserializing an empty list:

var ser = new XmlSerializer(typeof(Foo));
ser.Deserialize(new StringReader("<Foo MyList='' />"));

AFAIK, this is perfectly legal XML, but the XmlSerializer will throw an InvalidOperationException:

System.InvalidOperationException: There is an error in XML document (1, 6). ---> System.FormatException: Input string was not in a correct format.
   at System.Number.StringToNumber(String str, NumberStyles options, NumberBuffer& number, NumberFormatInfo info, Boolean parseDecimal)
   at System.Number.ParseInt32(String s, NumberStyles style, NumberFormatInfo info)
   at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderFoo.Read2_Foo(Boolean isNullable, Boolean checkType)
   at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderFoo.Read3_Foo()
   --- End of inner exception stack trace ---
   at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle, XmlDeserializationEvents events)
   at System.Xml.Serialization.XmlSerializer.Deserialize(TextReader textReader)
   at Blah.Program.Main(String[] args) in Program.cs:line 17

(This exception is from .NET 4.7.2; .NET Core 2.2 throws the same exception with almost identical stack trace.) The exception makes sense, as "" is not an integer.

There is this similar question, but it’s about enums, and I don’t know how to use the answer there for ints.

How can I get deserializing of an empty list working without implementing IXmlSerializable (what involves a lot of additional coding)?

Martin
  • 1,986
  • 15
  • 32
  • I think `MyList` should be a nullable array. – Aria May 29 '19 at 09:03
  • @Aria True, but I had `#nullable disable`. – Martin May 29 '19 at 09:14
  • You have a schema and getting an exception because the XML file is not matching the schema. So why do you insist on working with an xml that doesn't adhere to the schema? – jdweng May 29 '19 at 09:35
  • @jdweng Could you please explain to me why the XML file does not match the schema? I thought it does. (Of course I don’t insist on working with an xml that doesn’t adhere to the schema.) – Martin May 29 '19 at 09:39
  • You attribute is '1 2 3' which is more than one integer. You schema is for a list of attributes with each attribute containing one integer. – jdweng May 29 '19 at 09:54
  • 1
    @jdweng no; the schema is one attribute containing a list of integers. – steve16351 May 29 '19 at 10:23

1 Answers1

1

I'm not sure there is any magic you can do with the serializer attributes to make this work, and as it's an attribute, you can't add a complex type to help hide away the problem. You could use a proxy property which handles the input as a string to work around the problem, which while it is not beautiful, avoids the need for a full blown IXmlSerializable implementation.

[Serializable]
public class Foo
{
    [XmlIgnore]
    public int[] MyList { get; set; }

    [XmlAttribute(AttributeName = "MyList")]
    public string MyListProxy
    {
        get
        {
            if (MyList == null) return String.Empty;
            return String.Join(" ", MyList);
        }
        set
        {
            MyList = String.IsNullOrWhiteSpace(value) ? new int[0] : value
                .Split(' ')
                .Select(a => int.Parse(a))
                .ToArray();
        }
    }
}
steve16351
  • 5,372
  • 2
  • 16
  • 29