如何使用XmlSerializer将异构子节点反序列化为集合?

Cra*_*aig 6 .net c# xml xmlserializer

我正在使用C#/ .NET反序列化类似于此的XML文件:

<?xml version="1.0" encoding="utf-8" ?>
<Books>
  <Book
    Title="Animal Farm"
    >
    <Thing1>""</Thing1>
    <Thing2>""</Thing2>
    <Thing3>""</Thing3>
    ...
    <ThingN>""</ThingN>
  </Book>
  ... More Book nodes ...
</Books>
Run Code Online (Sandbox Code Playgroud)

对于反序列化的XML,我的类看起来像:

[XmlRoot("Books")]
public class BookList
{
    // Other code removed for compactness. 

    [XmlElement("Book")]
    public List<Book> Books { get; set; }
}

public class Book
{
    // Other code removed for compactness. 

    [XmlAttribute("Title")]
    public string Title { get; set; }

    [XmlAnyElement()]
    public List<XmlElement> ThingElements { get; set; }

    public List<Thing> Things { get; set; }
}  

public class Thing
{
    public string Name { get; set; }
    public string Value { get; set; }
} 
Run Code Online (Sandbox Code Playgroud)

反序列化时,我希望将Book元素(<Thing1>到<ThingN>)的所有子节点反序列化为Book的Things集合.但是,我无法弄清楚如何实现这一目标.现在,我坚持在ThingElements集合中存储Thing节点(通过XmlAnyElement).

有没有办法将异构子节点反序列化为一个集合(非XmlElements)?

Jos*_*osh 2

如果您想将其序列化为一组简单的 KeyValuePair,您可以使用自定义结构来完成此操作。不幸的是,内置的通用 KeyValuePair 不起作用。

但是,考虑到以下类定义:

[XmlRoot("Books")]
public class BookList
{
    [XmlElement("Book")]
    public List<Book> Books { get; set; }
}

public class Book
{
    [XmlAttribute("Title")]
    public string Title { get; set; }

    [XmlElement("Attribute")]
    public List<AttributePair<String, String>> Attributes { get; set; }
}

[Serializable]
[XmlType(TypeName = "Attribute")]
public struct AttributePair<K, V>
{
    public K Key { get; set; }
    public V Value { get; set; }

    public AttributePair(K key, V val)
        : this()
    {
        Key = key;
        Value = val;
    }
}
Run Code Online (Sandbox Code Playgroud)

当我使用此信息序列化对象时,我得到一个如下所示的 XML 结构。

<?xml version="1.0"?>
<Books xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
       xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Book Title="To win a woman">
    <Attribute>
      <Key>Author</Key>
      <Value>Bob</Value>
    </Attribute>
    <Attribute>
      <Key>Publish Date</Key>
      <Value>1934</Value>
    </Attribute>
    <Attribute>
      <Key>Genre</Key>
      <Value>Romance</Value>
    </Attribute>
  </Book>
</Books>
Run Code Online (Sandbox Code Playgroud)

我还能够成功地将 XML 读回到对象中并打印出信息。

您可以在控制台应用程序中亲自测试一下以查看结果。

using(var file = File.OpenRead("booklist.xml"))
{
    var readBookCollection = (BookList)serializer.Deserialize(file);

    foreach (var book in readBookCollection.Books)
    {
        Console.WriteLine("Title: {0}", book.Title);

        foreach (var attributePair in book.Attributes)
        {
            Console.CursorLeft = 3;
            Console.WriteLine("Key: {0}, Value: {1}", 
                attributePair.Key, 
                attributePair.Value);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)