如何反序列化具有 2 个同名但元素具有不同数据类型的元素的 XML?
How do I deserialize XML that has 2 elements with the same name but the elements have different datatypes?
我正在使用 API returns XML。如果我用一组参数调用 API,我会返回看起来像这样的 XML:
类型 1:
<root>
<foos>
<foo>some</foo>
<foo>text</foo>
<foo>here</foo>
</foos>
</root>
但是如果我用另一组参数调用 API,我会返回 XML,看起来像这样:
类型 2:
<root>
<foos>
<foo>
<fooName>some</fooName>
<fooId>1</fooId>
<fooDate>11-8-2019</fooDate>
</foo>
<foo>
<fooName>text</fooName>
<fooId>2</fooId>
<fooDate>11-9-2019</fooDate>
</foo>
<foo>
<fooName>here</fooName>
<fooId>3</fooId>
<fooDate>11-10-2019</fooDate>
</foo>
</foos>
</root>
如果可能的话,我想将其建模为单个 C# 对象...这样我就可以反序列化 XML 中的任何一个,如下所示:
private root Deserialize(string xmlData)
{
var serializer = new XmlSerializer(typeof(root));
using (var reader = new StringReader(xmlData))
{
return (root)serializer.Deserialize(reader);
}
}
我尝试像这样对 XML class 进行建模:
[XmlRoot("root")]
public class Root
{
[XmlAttribute(AttributeName = "foos")]
public List<string> foos { get; set; }
}
当 class 看起来像这样时,我可以反序列化类型 1 的 xmlData(并且我得到一个字符串列表)。但是当我尝试反序列化类型 2 的 xmlData 时,一切都是空的...
如果我这样建模 XML class:
[XmlRoot("root")]
public class Root
{
[XmlAttribute(AttributeName = "foos")]
public List<Foo> foos { get; set; }
}
[XmlRoot("foo")]
public class Foo
{
[XmlAttribute(AttributeName = "fooName")]
public string FooName { get; set; }
[XmlAttribute(AttributeName = "fooId")]
public string FooId { get; set; }
[XmlAttribute(AttributeName = "fooDate")]
public string FooDate { get; set; }
}
然后我可以反序列化类型 2 的 xmlData(并且我得到一个复杂对象的列表)。但这当然不适用于类型 1 的 xmlData。
有没有办法在 C# 中对 classes 进行建模以处理这两种情况?
你可以做的是修改 Foo
以便它可以通过添加字符串值 属性 并用 [=28= 标记来捕获文本值和预期的嵌套子元素] 像这样:
[XmlRoot("root")]
public class Root
{
[XmlArray("foos")]
[XmlArrayItem("foo")]
public List<Foo> foos { get; set; }
}
[XmlRoot("foo")]
public class Foo
{
[XmlElement("fooName")]
public string FooName { get; set; }
[XmlElement("fooId")]
public string FooId { get; set; }
[XmlElement("fooDate")]
public string FooDate { get; set; }
[XmlText]
public string Value { get; set; }
}
备注:
-
Indicates to the XmlSerializer
that the member must be treated as XML text when the class that contains it is serialized or deserialized.
Foo
现在可以绑定到 mixed content 节点,例如
<foo>Some text<fooName>text</fooName>
<fooId>2</fooId>
<fooDate>11-9-2019</fooDate>
</foo>
我在上面更正了您现有的 Root
和 Foo
数据模型中的一些错误,包括:
<fooName>
、<fooId>
和<fooDate>
是子元素不是属性,所以它们对应的属性必须用[XmlElement]
.[=34来标记=]
foos
绑定到具有外部容器元素 <foos>
和内部顺序元素 <foo>
的序列,因此必须用 [XmlArray]
标记.
演示 fiddle here.
我正在使用 API returns XML。如果我用一组参数调用 API,我会返回看起来像这样的 XML:
类型 1:
<root>
<foos>
<foo>some</foo>
<foo>text</foo>
<foo>here</foo>
</foos>
</root>
但是如果我用另一组参数调用 API,我会返回 XML,看起来像这样:
类型 2:
<root>
<foos>
<foo>
<fooName>some</fooName>
<fooId>1</fooId>
<fooDate>11-8-2019</fooDate>
</foo>
<foo>
<fooName>text</fooName>
<fooId>2</fooId>
<fooDate>11-9-2019</fooDate>
</foo>
<foo>
<fooName>here</fooName>
<fooId>3</fooId>
<fooDate>11-10-2019</fooDate>
</foo>
</foos>
</root>
如果可能的话,我想将其建模为单个 C# 对象...这样我就可以反序列化 XML 中的任何一个,如下所示:
private root Deserialize(string xmlData)
{
var serializer = new XmlSerializer(typeof(root));
using (var reader = new StringReader(xmlData))
{
return (root)serializer.Deserialize(reader);
}
}
我尝试像这样对 XML class 进行建模:
[XmlRoot("root")]
public class Root
{
[XmlAttribute(AttributeName = "foos")]
public List<string> foos { get; set; }
}
当 class 看起来像这样时,我可以反序列化类型 1 的 xmlData(并且我得到一个字符串列表)。但是当我尝试反序列化类型 2 的 xmlData 时,一切都是空的...
如果我这样建模 XML class:
[XmlRoot("root")]
public class Root
{
[XmlAttribute(AttributeName = "foos")]
public List<Foo> foos { get; set; }
}
[XmlRoot("foo")]
public class Foo
{
[XmlAttribute(AttributeName = "fooName")]
public string FooName { get; set; }
[XmlAttribute(AttributeName = "fooId")]
public string FooId { get; set; }
[XmlAttribute(AttributeName = "fooDate")]
public string FooDate { get; set; }
}
然后我可以反序列化类型 2 的 xmlData(并且我得到一个复杂对象的列表)。但这当然不适用于类型 1 的 xmlData。
有没有办法在 C# 中对 classes 进行建模以处理这两种情况?
你可以做的是修改 Foo
以便它可以通过添加字符串值 属性 并用 [=28= 标记来捕获文本值和预期的嵌套子元素] 像这样:
[XmlRoot("root")]
public class Root
{
[XmlArray("foos")]
[XmlArrayItem("foo")]
public List<Foo> foos { get; set; }
}
[XmlRoot("foo")]
public class Foo
{
[XmlElement("fooName")]
public string FooName { get; set; }
[XmlElement("fooId")]
public string FooId { get; set; }
[XmlElement("fooDate")]
public string FooDate { get; set; }
[XmlText]
public string Value { get; set; }
}
备注:
-
Indicates to the
XmlSerializer
that the member must be treated as XML text when the class that contains it is serialized or deserialized. Foo
现在可以绑定到 mixed content 节点,例如<foo>Some text<fooName>text</fooName> <fooId>2</fooId> <fooDate>11-9-2019</fooDate> </foo>
我在上面更正了您现有的
Root
和Foo
数据模型中的一些错误,包括:<fooName>
、<fooId>
和<fooDate>
是子元素不是属性,所以它们对应的属性必须用[XmlElement]
.[=34来标记=]foos
绑定到具有外部容器元素<foos>
和内部顺序元素<foo>
的序列,因此必须用[XmlArray]
标记.
演示 fiddle here.