使用泛型C#反序列化动态XML

时间:2018-03-20 10:08:46

标签: c# xml xml-deserialization

给出以下XML:

<RESPONSE version="10">
    <RESULTS MyAttribute="1" />
</RESPONSE>

我可以像这样反序列化:

[XmlRoot("RESPONSE")]
public class Response
{
    [XmlElement(ElementName = "RESULTS")]
    public Results Results {get;set;}
}

public class Results
{
    [XmlAttribute(AttributeName = "MyAttribute")]
    public bool MyAttribute { get; set; }
}

var serializer = new XmlSerializer(typeof(Response));
var result = (Response)serializer.Deserialize(new StringReader(xml));

这很有效。 但问题是我想要反序列化以下XML,并且我不想复制Response类,我想使用通用方法。

<RESPONSE version="10">
    <SOCCER AnotherAttribute="1" />
</RESPONSE>

我尝试过以下操作:

[XmlRoot("Response")]
public class Response<T>
{
    public T Data {get;set;}
}

public class SoccerRoot
{
    [XmlElement(ElementName = "SOCCER")]
    public class Soccer {get;set;}
}

public class Soccer
{
    [XmlAttribute(AttributeName = "AnotherAttribute")]
    public bool AnotherAttribute {get;set;}
}


var serializer = new XmlSerializer(typeof(Response<SoccerRoot>));
var result = (Response<SoccerRoot>)serializer.Deserialize(new StringReader(xml));

但这不起作用,我也试图继承Response类但没有运气。 我收到以下错误:<xmlns='' > was not expected.

我在这里是正确的方式,还是在反序列化XML文件时不可能使用通用方法?

2 个答案:

答案 0 :(得分:3)

使用Response<SoccerRoot>,预期的xml布局为:

<RESPONSE>
    <Data>
        <SOCCER AnotherAttribute=...>
匹配。无法使用属性自定义T Data 的元素名称。

选项:

  • 有多个根对象(SOCCERRESULTS等各一个):

    [XmlRoot("RESPONSE")]
    public class SoccerRoot {
        [XmlElement("SOCCER")]
        public Soccer Soccer {get;set;}
    }
    [XmlRoot("RESPONSE")]
    public class ResultsRoot {
        [XmlElement("RESULTS")]
        public Results Results {get;set;}
    }
    
  • 有一个具有多个第一级子项的根对象(一个用于SOCCER,一个用于RESULTS等等 - 每个类型

    [XmlRoot("RESPONSE")]
    public class Response {
        [XmlElement("RESULTS")]
        public Results Results {get;set;}
        [XmlElement("SOCCER")]
        public Soccer Soccer {get;set;}
    }
    
  • 使用泛型方法,但丢失了中间对象,因此您Response<Soccer>(完全删除SoccerRoot),并使用XmlAttributeOverrides自定义元素名称确保缓存XmlSerializer生成的(否则会以惊人的速度泄漏)

坦率地说,我会选择前两个选项中的任何一个,而单独留下第三个选项。

答案 1 :(得分:1)

尝试创建一个包含对象RESULTS和SOCCER的公共类,然后根据数据,一个将为null,其他将包含值。

class Program
{
    static void Main(string[] args)
    {
        //
        var xml = "<RESPONSE  version=\"1\" ><SOCCER AnotherAttribute =\"1\" /></RESPONSE>";
        var serializer = new XmlSerializer(typeof(Response<int>));
        var result = (Response<int>)serializer.Deserialize(new StringReader(xml));

        xml = "<RESPONSE version=\"10\"><RESULTS MyAttribute = \"1\" /></RESPONSE >";
        result = (Response<int>)serializer.Deserialize(new StringReader(xml));
        Console.ReadLine();
    }
}

[XmlRoot("RESPONSE")]
public class Response<T>
{
    [XmlAttribute(AttributeName = "version")]
    public T Version { get; set; }

    [XmlElement(ElementName = "SOCCER")]
    public SoccerRoot SoccerRoot { get; set; }

    [XmlElement(ElementName = "RESULTS")]
    public Results Results { get; set; }
}
public class SoccerRoot
{
    [XmlAttribute(AttributeName = "AnotherAttribute")]
    public int AnotherAttribute { get; set; }
}

public class Results
{
    [XmlAttribute(AttributeName = "MyAttribute")]
    public bool MyAttribute { get; set; }
}