【问题标题】:Deserialize dynamic XML with generics C#使用泛型 C# 反序列化动态 XML
【发布时间】:2018-08-29 02:21:28
【问题描述】:

给定以下 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 文件时不能使用通用方法?

【问题讨论】:

  • 在任何一种情况下都不起作用; [XmlRoot("Response")]&lt;RESPONSE&gt; 不匹配。这是实际代码,还是您将其匿名化了?特别是,如果是这样:最后一个错误中提到的 xmlns 让我想知道那里的实际问题是否已经在匿名化中丢失了
  • 我已经匿名了,有点抱歉,会修复它。 xmlns 根本不存在于 xml 中,xml 现在是正确的,我是用手机写的,所以我现在无法访问代码,但我认为您无论如何都能理解我所追求的概念?

标签: c# xml xml-deserialization


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

    使用Response&lt;SoccerRoot&gt;,预期的 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&lt;Soccer&gt;(完全删除SoccerRoot),并使用XmlAttributeOverrides自定义元素名称,一定要缓存@ 987654333@已生成(否则会以惊人的速度泄漏)

    坦率地说,我会选择前两个选项中的任何一个,而不要理会第三个。

    【讨论】:

    • 谢谢,我将使用第一个解决方案,只是想看看他们是否有任何我不知道的方法
    • @JOSEFtw 好吧,有 XmlAttributeOverrides 没有多少人知道,可以在这里使用(不方便,但可以),但它是一个非常复杂的工具,如果使用不当:你会很快耗尽内存;所以:您可能已经发现了一件新事物:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-05-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多