Вы можете отредактировать схему, чтобы указать, что значение AverageSpeed ​​не может быть пустым. Это требует, чтобы все, что производит XML, действительно следовало схеме.

лкиваюсь с довольно раздражающей проблемой при попытке десериализации конкретного XML-документа с помощью метода XmlSerializer.Deserialize ().

По сути, у меня есть строго типизированный XSD с элементом типа double. При попытке десериализации элемента для конкретного XML-документа я получаю обычное «System.FormatException: входная строка была в неправильном формате». исключение, потому что в этом конкретном документе элемент не имеет значения.

Вот код для вас, кретин.

Образец XML-документа:

<TrackInfo>
  <Name>Barcelona</Name>
  <Length>4591</Length>
  <AverageSpeed />
</TrackInfo>

XSD:

<?xml version="1.0" encoding="utf-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="TrackInfo">
  <xs:complexType>
    <xs:sequence>
      <xs:element name="Name" type="xs:string" />
      <xs:element name="Length" type="xs:double" default="0.0" />
      <xs:element name="AverageSpeed" type="xs:double" default="0.0" />
    </xs:sequence>
  </xs:complexType>
</xs:element>

Класс TrackInfo:

[Serializable]
public class TrackInfo
{
  private string name = string.Empty;
  private double length = 0.0;
  private double averageSpeed = 0.0;

  [XmlElement]
  public string Name
  { ... }

  [XmlElement]
  public double Length
  { ... }

  [XmlElement]
  public double AverageSpeed
  { ... }
}

Пример кода десериализации:

XmlDocument xmlDocument = new XmlDocument();
xmlDocument.Load("TrackInfo.xml");

// Deserialise XML string into TrackInfo object
byte[] buffer = ASCIIEncoding.UTF8.GetBytes(xmlDocument.InnerXml);
MemoryStream stream = new MemoryStream(buffer);
System.Xml.XmlReader reader = new System.Xml.XmlTextReader(stream);

XmlSerializer xSerializer = new System.Xml.Serialization.XmlSerializer(typeof(TrackInfo));
TrackInfo trackInfo = (TrackInfo)xSerializer.Deserialize(reader);

Я знаю, что исключение десериализации происходит из-за того, что пустая строка не может быть преобразована в двойную. Я также знаю, что значение по умолчанию не присваивается AverageSpeed, потому что фактически пустая строка является совершенно приемлемым значением.

Есть ли простой способ установить двойные значения по умолчанию на 0.0 (или любой другой тип) при десериализации, если в документе XML найдено пустое строковое значение? В идеале я бы хотел избежать реализации ISerializable, потому что мне не хочется тратить оставшуюся часть дня в горящей яме ада (т. Е. Внедрять ISerializable для примерно ста классов).

Ура! Жан-Мишель

Ответы на вопрос(4)

чтобы указать, что значение AverageSpeed ​​не может быть пустым. Это требует, чтобы все, что производит XML, действительно следовало схеме.

<?xml version="1.0" encoding="utf-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="TrackInfo">
  <xs:complexType>
    <xs:sequence>
      <xs:element name="Name" type="xs:string" />
      <xs:element name="Length" type="xs:double" default="0.0" />
      <xs:element name="AverageSpeed" type="xs:double" default="0.0" nillable="false" />
    </xs:sequence>
  </xs:complexType>
</xs:element>

удваивать? (с вопросительным знаком или Nullable <double>). Это позволяет вашему типу значения хранить нулевое значение, и десериализатор не будет подавлять нулевое значение.

http://msdn.microsoft.com/en-us/library/system.componentmodel.defaultvalueattribute.aspx

Примечание: Атрибут DefaultValueAttribute не приведет к автоматической инициализации элемента со значением атрибута. Вы должны установить начальное значение в вашем коде.

Я думаю, что инициализация поля всегда будет иметь приоритет над значением DefaultValueAttribute. В любом случае, это именно то, что я искал.

Большое спасибо тебе, Себастьян!

Решение Вопроса

Вы можете указать значение по умолчанию, как

    [XmlElement]
    [System.ComponentModel.DefaultValueAttribute(0.0)]
    public double AverageSpeed
    { ... }

/ редактировать: хорошо, странный beaviour здесь. Что бы я ни указывал в качестве значения в Атрибуте, это всегда значение поля:

private double averageSpeed = 2.0;

Но никаких исключений не происходит.

Ваш ответ на вопрос