Ошибка десериализации XML-документа со строго типизированным XSD - PullRequest
2 голосов
/ 20 января 2009

Я столкнулся с довольно раздражающей проблемой при попытке десериализации конкретного 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 ]

3 голосов
/ 20 января 2009

Ознакомьтесь с документацией MSDN на DefaultValueAttribute: http://msdn.microsoft.com/en-us/library/system.componentmodel.defaultvalueattribute.aspx

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

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

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

1 голос
/ 20 января 2009

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

1 голос
/ 20 января 2009

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

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

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

private double averageSpeed = 2.0;

Но исключений не возникает.

0 голосов
/ 20 января 2009

Вы можете отредактировать схему, указав, что значение AverageSpeed ​​не может иметь значение NULL. Это требует, чтобы все, что производит 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>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...