简体   繁体   English

如何将多个IXmlSerializable序列化为一个XML文件?

[英]How to serialize more than one IXmlSerializable into one XML file?

I have created a few specialized data structures that implements IXmlSerializable. 我创建了一些实现IXmlSerializable的专用数据结构。 At runtime, I want to serialize these instances into a single XML document (and deserialize). 在运行时,我想将这些实例序列化为单个XML文档(并反序列化)。

Serializing to different files, XML result is correct. 序列化到不同的文件,XML结果是正确的。 But when I tried to call XmlSerializer.Serialize consecutive times on a single StreamWriter for different data structures, the result is that it adds the XML declaration on each call, resulting in invalid XML. 但是当我尝试在单个StreamWriter上连续调用XmlSerializer.Serialize不同数据结构的结果时,结果是它在每次调用时都添加了XML声明,从而导致无效的XML。

What is the proper way to do this? 正确的方法是什么?

Do I need a wrapper parent class? 我需要包装父类吗? If I use another parent class to wrap these data structures, and then serialize the parent class, how should I write implement IXmlSerialize at the parent? 如果我使用另一个父类包装这些数据结构,然后序列化该父类,则应如何在父类上编写实现IXmlSerialize

Do I need a wrapper parent class? 我需要包装父类吗?

Yes. 是。 The XmlSerializer isn't that smart. XmlSerializer不是那么聪明。 It outputs an XML file. 它输出一个XML文件。 It doesn't take into account that it might have some content already. 它没有考虑到它可能已经包含一些内容。 You just get two XML files in one. 您只需将两个XML文件合而为一。

If fact, you don't need to implement IXmlSerializable at all if your data structure is simple. 实际上,如果您的数据结构很简单,则根本不需要实现IXmlSerializable You can just serialize any class. 您可以序列化任何类。 This structure will suffice: 这个结构就足够了:

public class ParentClass
{
    public Class1 FirstClass {get;set;}
    public Class2 SecondClass {get;set;}
}

Just stuff it with your instances and you can XML serialize them. 只需将其填充到您的实例中,即可对它们进行XML序列化。


In my case, I have an extension method to do all the serialization for me. 就我而言,我有一个扩展方法可以为我完成所有序列化。 This is it: 就是这个:

public static string ToXml<T>(this T value)
{
    StringWriter stringWriter = new StringWriter();

    string xml;

    XmlSerializer xmlserializer = new XmlSerializer(typeof(T));

    using (XmlWriter writer = XmlWriter.Create(stringWriter, new XmlWriterSettings { Indent = true }))
    {
        writer.WriteStartDocument();

        xmlserializer.Serialize(writer, value);
        writer.WriteEndDocument();

        xml = stringWriter.ToString();
    }

    return xml;
}

Then you can just call: 然后,您可以致电:

string xml = someInstanceOfParent.ToXml();

Save that as you like. 随意保存。

We can use the following approach: while serializing we write root node manually, then while deserializing skip this node manually. 我们可以使用以下方法:序列化时,我们手动写入根节点,然后反序列化时,手动跳过此节点。

public class One
{
    public string Foo { get; set; }
}

public class Two
{
    public string Bar { get; set; }
}


var one = new One { Foo = "foo" };
var two = new Two { Bar = "bar" };

// Serialization two different class in one file
var settings = new XmlWriterSettings { Indent = true };
using (var writer = XmlWriter.Create("test.txt", settings))
{
    // Create root node
    writer.WriteStartElement("root");

    var xs = new XmlSerializer(typeof(One));
    xs.Serialize(writer, one);

    xs = new XmlSerializer(typeof(Two));
    xs.Serialize(writer, two);
}

// Deserialization two different class from one file
using (var reader = XmlReader.Create("test.txt"))
{
    // Skip root node
    reader.ReadToFollowing("One"); // Name of first class

    var xs = new XmlSerializer(typeof(One));
    One first = (One)xs.Deserialize(reader);

    xs = new XmlSerializer(typeof(Two));
    Two second = (Two)xs.Deserialize(reader);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM