C# 使用强类型XSD反序列化XML文档时出错

C# 使用强类型XSD反序列化XML文档时出错,c#,xml,xsd,serialization,C#,Xml,Xsd,Serialization,我在尝试使用XmlSerializer.Deserialize()方法反序列化特定XML文档时遇到了一个相当恼人的问题 基本上,我有一个强类型的XSD,其元素类型为double。当尝试对特定XML文档的元素进行反序列化时,我得到了通常的“System.FormatException:输入字符串格式不正确”异常,因为在该特定文档中,元素没有值 这是给你们这些书呆子的一些代码 示例XML文档: <TrackInfo> <Name>Barcelona</Name>

我在尝试使用XmlSerializer.Deserialize()方法反序列化特定XML文档时遇到了一个相当恼人的问题

基本上,我有一个强类型的XSD,其元素类型为double。当尝试对特定XML文档的元素进行反序列化时,我得到了通常的“System.FormatException:输入字符串格式不正确”异常,因为在该特定文档中,元素没有值

这是给你们这些书呆子的一些代码

示例XML文档:

<TrackInfo>
  <Name>Barcelona</Name>
  <Length>4591</Length>
  <AverageSpeed />
</TrackInfo>
<?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>
[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);
我知道,反序列化异常来自一个事实,即空字符串不能转换为double。我还知道默认值没有分配给AverageSpeed,因为实际上,空字符串是一个完全可以接受的值

如果在XML文档中发现空字符串值,反序列化时是否有一种简单的方法可以将双精度值默认为0.0(或任何其他类型)? 理想情况下,我希望避免实现ISerializable,因为我真的不想把剩下的时间花在地狱的深渊中(例如,实现大约100个类的ISerializable)

干杯!
Jean-Michel

您可以编辑模式以指定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>


一个可能的解决方案是使用double?(带问号,或可为空)。这允许您的值类型存储空值,并且反序列化程序不会被空值阻塞。

您可以指定默认值,如

    [XmlElement]
    [System.ComponentModel.DefaultValueAttribute(0.0)]
    public double AverageSpeed
    { ... }
/编辑:好的,这里有奇怪的动物。无论我在属性中设置了什么值,它总是字段值:

private double averageSpeed = 2.0;

但不会发生异常。

查看有关DefaultValueAttribute的MSDN文档:

注意:DefaultValueAttribute不会导致成员 自动初始化为 属性的值。你必须设置 代码中的初始值

我认为字段初始化将始终优先于DefaultValueAttribute值。无论如何,这似乎正是我想要的

非常感谢你,塞巴斯蒂安