想象一下如下所示的XML结构:
[XmlRoot("Foo")]
public class Foo
{
[XmlElement("Bar")]
public Bar Bar { get; set; }
[XmlElement("SuperImportant")]
public SuperImportant SuperImportant { get; set; }
}
[XmlRoot("Bar")]
public class Bar
{
[XmlElement("Baz")]
public XmlElement Baz { get; set; }
}
[XmlRoot("SuperImportant")]
public class SuperImportant
{
[XmlElement("MegaImportant")]
public string MegaImportant { get; set; }
}
由于某种原因,Baz被定义为XmlElement
。
现在查看此代码:
var template = @"
<Foo>
<Bar>
{0}
</Bar>
<SuperImportant>
<MegaImportant>42</MegaImportant>
</SuperImportant>
</Foo>";
var selfClosed = new StringReader(String.Format(template, "<Baz/>"));
var openClosePair = new StringReader(String.Format(template, "<Baz></Baz>"));
XmlSerializer xmlSerializer = new XmlSerializer(typeof(Foo));
var o1 = (Foo)xmlSerializer.Deserialize(selfClosed);
Console.WriteLine(o1.SuperImportant == null); // True, it's not there
var o2 = (Foo)xmlSerializer.Deserialize(openClosePair);
Console.WriteLine(o2.SuperImportant == null); // False, it's there
如您所见,如果类定义中定义为XmlElement
的某些标记似乎是自闭的,则其父标记后面的元素为null
。如何配置XmlSerializer
将自闭标记视为开 - 关对?在这两种情况下都应该对SuperImportant
进行反序列化,但它不在前者中,这是错误的。
答案 0 :(得分:1)
您应该将Baz
标记为[XmlAnyElement("Baz")]
,如下所示:
[XmlRoot("Bar")]
public class Bar
{
[XmlAnyElement("Baz")]
public XmlElement Baz { get; set; }
}
如docs中所述,此属性
指定成员(返回XmlElement或XmlNode个对象数组的字段)包含表示在被序列化或反序列化的对象中没有相应成员的任何XML元素的对象。
...
您还可以将XmlAnyElementAttribute应用于返回单个XmlElement对象的字段。如果这样做,则必须使用XmlElement类的属性和方法递归迭代未知元素。
应用属性后,Baz
属性将正确捕获<Baz/>
和<Baz></Baz>
元素,而不会干扰后续节点的反序列化。 [XmlElement("Baz")]
导致您看到的不一致似乎很奇怪,但由于[XmlAnyElement("Baz")]
旨在处理这种情况,因此应该使用它。
示例工作.Net小提琴here。