c# - 如何反序列化具有 2 个同名元素但元素具有不同数据类型的 XML?

标签 c# xml xmlserializer

我正在使用返回 XML 的 API。如果我使用一组参数调用 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 类建模:

[XmlRoot("root")]
public class Root
{
    [XmlAttribute(AttributeName = "foos")]
    public List<string> foos { get; set; }              
}

当类看起来像这样时,我可以反序列化类型 1 的 xmlData(并且我得到一个字符串列表)。但是当我尝试反序列化 Type 2 的 xmlData 时,一切都是空的......

如果我像这样对 XML 类建模:

[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# 中对类建模以处理这两种情况?

最佳答案

你能做的就是修改Foo这样它就可以通过添加字符串值属性并用 [XmlText] 标记来捕获文本值和预期的嵌套子元素。像这样:

[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; }
}

注意事项:

  1. XmlTextAttribute

    Indicates to the XmlSerializer that the member must be treated as XML text when the class that contains it is serialized or deserialized.

  2. Foo现在可以绑定(bind)到 mixed content节点如

    <foo>Some text<fooName>text</fooName>
      <fooId>2</fooId>
      <fooDate>11-9-2019</fooDate>
    </foo>
    
  3. 您现有的 Root 中存在一些错误和 Foo我在上面更正的数据模型,包括:

    • <fooName> , <fooId><fooDate>是子元素不是属性,所以它们对应的属性必须用 [XmlElement] 标记.

    • foos绑定(bind)到具有外部容器元素的序列 <foos>和内部顺序元素 <foo>所以必须标有 [XmlArray] .

演示 fiddle here .

关于c# - 如何反序列化具有 2 个同名元素但元素具有不同数据类型的 XML?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58773967/

相关文章:

c# - 征求意见 : fast hashed base class for dictonary keys

android - 将 ConstraintLayout 内的 FrameLayout 对齐到底部

xml - XSD 架构 - 多次使用相同的 namespace

c# - 如何对字典进行 XML 序列化

c# - 有没有办法使用 XmlSerializer 执行以下操作?

c# - 比较转换为对象的值类型

c# - UWP 无法激活 Windows 应用商店应用程序错误 : the app didn't start

c# - CloudConfigurationManager.GetSetting 在生产中返回空字符串?

xml - XPath-是否可以查询节点内容?

c# - 元组无法序列化,因为它没有无参数构造函数