如何反序列化包含两个具有相同名称但元素具有不同数据类型的元素的XML?

我正在使用返回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; }              
}

当类看起来像这样时,我可以反序列化Type 1的xmlData(并且我会得到一个字符串列表)。但是当我尝试反序列化类型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#中对类进行建模以处理这两种情况?

ooohwj 回答:如何反序列化包含两个具有相同名称但元素具有不同数据类型的元素的XML?

您可以做的是修改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

      

    XmlSerializer表示,对包含该成员的类进行序列化或反序列化时,必须将该成员视为XML文本。

  2. Foo现在将能够绑定到mixed content节点,例如

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

    • <fooName><fooId><fooDate>是子元素而不是属性,因此它们的相应属性必须标记为[XmlElement]

    • foos绑定到具有外部容器元素<foos>和内部顺序元素<foo>的序列,因此必须标记为[XmlArray]

演示小提琴here

本文链接:https://www.f2er.com/3135026.html

大家都在问