【问题标题】:Error deserialising XML document with strongly typed XSD使用强类型 XSD 反序列化 XML 文档时出错
【发布时间】:2010-10-02 11:21:26
【问题描述】:

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

基本上,我有一个带有 double 类型元素的强类型 XSD。当尝试反序列化特定 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,因为实际上空字符串是一个完全可以接受的值。

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

干杯! 让-米歇尔

【问题讨论】:

    标签: c# xml xsd serialization


    【解决方案1】:

    查看有关 DefaultValueAttribute 的 MSDN 文档: http://msdn.microsoft.com/en-us/library/system.componentmodel.defaultvalueattribute.aspx

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

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

    非常感谢塞巴斯蒂安!

    【讨论】:

      【解决方案2】:

      你可以像这样指定默认值

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

      /edit: 好的,奇怪的行为在这里。无论我在属性中设置什么值,它始终是字段值:

      private double averageSpeed = 2.0;
      

      但是没有异常发生。

      【讨论】:

        【解决方案3】:

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

        【讨论】:

          【解决方案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>
          

          【讨论】:

            猜你喜欢
            • 2015-11-07
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-08-28
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多