考虑以下XML:
<a>
<b>2</b>
<c></c>
</a>
我需要将这个xml反序列化为一个对象。所以,我写了下面的课。
public class A
{
[XmlElement("b", Namespace = "")]
public int? B { get; set; }
[XmlElement("c", Namespace = "")]
public int? C { get; set; }
}
由于我使用的是nullables,所以在取消对上述xml的序列化时,我希望得到一个具有null C属性的对象A。
相反,我得到一个异常,告诉文档有一个错误。
缺少元素的和空元素之间存在差异。
缺少元素<a><b>2</b></a>
。这里,C将使用DefaultValue属性,采用您指定的任何默认值,如果没有显式默认值,则为null。
一个空元素<a><b>2</b><c xs:Nil='true'/></a>
。在这里,您将获得null。
当您执行<a><b>2</b><c></c><a/>
时,xml序列化程序将尝试解析字符串。作为整数为空将正确失败。
由于您的提供程序正在生成无效的xml,因此如果使用XmlSerializer:,则需要执行此操作
[XmlRoot(ElementName = "a")]
public class A
{
[XmlElement(ElementName = "b")]
public int? B { get; set; }
[XmlElement(ElementName = "c")]
public string _c { get; set; }
public int? C
{
get
{
int retval;
return !string.IsNullOrWhiteSpace(_c) && int.TryParse(_c, out retval) ? (int?) retval : null;
}
}
}
或者使用DataContractSerializer 稍微好一点
[DataContract(Name="a")]
public class A1
{
[DataMember(Name = "b")]
public int? B { get; set; }
[DataMember(Name = "c")]
private string _c { get; set; }
public int? C
{
get
{
int retval;
return !string.IsNullOrWhiteSpace(_c) && int.TryParse(_c, out retval) ? (int?)retval : null;
}
}
}
尽管DataContractSerializer不支持属性(如果有问题的话)。
要反序列化示例中的空标记,如"c":
<foo>
<b>2</b>
<c></c>
</foo>
我使用了这种方法。首先,它使用LINQ从XML文件中删除null或空元素,然后将没有null或空标记的新文档反序列化到Foo类。
public static Foo ReadXML(string file)
{
Foo foo = null;
XDocument xdoc = XDocument.Load(file);
xdoc.Descendants().Where(e => string.IsNullOrEmpty(e.Value)).Remove();
XmlSerializer xmlSer = new XmlSerializer(typeof(Foo));
using (var reader = xdoc.Root.CreateReader())
{
foo = (Foo)xmlSer.Deserialize(reader);
reader.Close();
}
if (foo == null)
foo = new Foo();
return foo;
}
这将为您提供缺失属性的默认值。
foo.b = 2;
foo.c = 0; //for example, if it's an integer
我加入了来自链接的信息:
删除空的XML标记
使用XDocument作为XmlSerializer的源。是否反序列化?