在XML反序列化中处理空字符串为空

时间:2011-05-24 21:55:08

标签: .net xml serialization null

关于this question,我遇到了同样的问题。我使用基于SOAP的API来回发送数据,其中响应不符合标准,特别是使用空值。对于DateTime,API将发回一个空字符串,如下所示:

<nextreview></nextreview>

导致反序列化时出现以下错误:

  

字符串''不是有效的AllXsd值。

所以我的想法是创建一个自定义Nullable类型NullableOrEmpty<T>,实现IXMLSerializable通过将空字符串转换为null来处理空字符串。问题是我只想处理空字符串的例外情况。我希望使用“默认”行为正常序列化和反序列化其他所有内容。如何在下面的代码中模拟序列化的默认行为?

public class NullableOrEmpty<T> : IXmlSerializable
    where T : struct
{
    public T? NullableValue { get; set; }
    public T Value { get { return this.NullableValue.Value; } }
    public bool HasValue { get { return this.NullableValue.HasValue; } }

    ...

    public void ReadXml(XmlReader reader)
    {
        string xml = reader.ReadElementContentAsString();
        if (string.IsNullOrEmpty(xml))
        {
            this.NullableValue = null;
        }
        else
        {
            //THIS SHOULD DO THE DEFAULT. THIS DOESN'T WORK.  WHAT DO I DO??
            //this.NullableValue = (T?)new XmlSerializer(typeof(T?)).Deserialize(reader);
        }
    }

    public void WriteXml(XmlWriter writer)
    {
        //THIS SHOULD DO THE DEFAULT.  THIS DOESN'T WORK. WHAT DO I DO??
        //new XmlSerializer(typeof(T?)).Serialize(writer, this.NullableValue);
    }

}

当我说“这不起作用”时,它会专门生成以下错误消息,可能是因为它试图消耗不存在的东西:

  

XML文档中存在错误(63,   6)。

     

<lastreview xmlns=''>不是   预期

这是一个XML片段。该错误是由birthdate中的值引起的,因为在实际给出值的非例外情况下我没有正确使用它:

<udf4></udf4>
<udf3></udf3>
<birthdate>1978-05-24Z</birthdate>
<lastreview></lastreview>
<fulltime>1</fulltime>

任何想法或想法都表示赞赏。如果需要,我可以发布更多代码示例或测试出建议。谢谢!

2 个答案:

答案 0 :(得分:3)

你可以在这做一件事,虽然可能更痛苦的是实现适配器模式,你从xml结果填充的对象只有string类型的属性,然后写一个转换器方法来填充你的'当目标属性为DateTime时,对象检查空字符串。它可能比实现自己的序列化器更容易。

答案 1 :(得分:0)

我不再使用这个类了(我需要第三方验证),但实际上我可以通过使用XmlConvert帮助程序手动处理所有数据类型来使其工作:

public void ReadXml(XmlReader reader)
{
    string xml = reader.ReadElementContentAsString();
    if (string.IsNullOrEmpty(xml))
    {
        this.NullableValue = null;
    }
    else
    {
        if (this.NullableValue is bool)
            this.NullableValue = (T?)Convert.ChangeType(XmlConvert.ToBoolean(xml), typeof(T?));
        else if (this.NullableValue is byte)
            this.NullableValue = (T?)Convert.ChangeType(XmlConvert.ToByte(xml), typeof(T?));
        else if (this.NullableValue is char)
            this.NullableValue = (T?)Convert.ChangeType(XmlConvert.ToChar(xml), typeof(T?));
        else if (this.NullableValue is DateTime)
            this.NullableValue = (T?)Convert.ChangeType(XmlConvert.ToDateTime(xml), typeof(T?));
        else if (this.NullableValue is decimal)
            this.NullableValue = (T?)Convert.ChangeType(XmlConvert.ToDecimal(xml), typeof(T?));
        else if (this.NullableValue is double)
            this.NullableValue = (T?)Convert.ChangeType(XmlConvert.ToDouble(xml), typeof(T?));
        else if (this.NullableValue is Guid)
            this.NullableValue = (T?)Convert.ChangeType(XmlConvert.ToGuid(xml), typeof(T?));
        else if (this.NullableValue is short)
            this.NullableValue = (T?)Convert.ChangeType(XmlConvert.ToInt16(xml), typeof(T?));
        else if (this.NullableValue is int)
            this.NullableValue = (T?)Convert.ChangeType(XmlConvert.ToInt32(xml), typeof(T?));
        else if (this.NullableValue is long)
            this.NullableValue = (T?)Convert.ChangeType(XmlConvert.ToInt64(xml), typeof(T?));
        else if (this.NullableValue is float)
            this.NullableValue = (T?)Convert.ChangeType(XmlConvert.ToSingle(xml), typeof(T?));
    }
}

public void WriteXml(XmlWriter writer)
{
    new XmlSerializer(typeof(T?)).Serialize(writer, this.NullableValue);
}