在XML反序列化中将空字符串处理为空
问题描述:
对于this question,我有同样的问题。我使用基于SOAP的API来回发送数据,其中响应不符合标准,特别是空值。对于DateTime
,该API将发送回一个空字符串,像这样:在XML反序列化中将空字符串处理为空
<nextreview></nextreview>
导致反序列化上出现以下错误:
字符串“”不是一个有效的AllXsd值。
所以我的想法是创建一个自定义空类型,NullableOrEmpty<T>
,通过转换为null实施IXMLSerializable
,处理空字符串。问题是我只想处理空字符串的例外情况。我想用正常的序列化和反序列化来使用'默认'行为。我如何在下面的代码中模拟序列化的默认行为?
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>
任何想法或想法赞赏。如果需要,我可以发布更多代码示例或测试出建议。谢谢!
答
你可以在这里做的一件事,尽管它可能更多的痛苦是实现适配器模式,其中从xml结果填充的对象只具有字符串类型的属性,然后编写一个转换器方法来填充当目标属性是DateTime时,'真实'对象检查空字符串。这可能比实现自己的序列化器更容易。
答
我不再使用这个类(我需要通过,而不是第三方验证),但我实际上是能够通过使用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);
}
你不能使用相同的'XmlReader'。您已经阅读过要再次阅读的内容。 – 2011-05-24 22:01:15