views:

44

answers:

1

Hi, is it possible to use the XmlSerializer in .NET to load an XML file which includes other XML files? And how?

This, in order to share XML state easily in two "parent" XML files, e.g. AB and BC in below.

Example:

using System;
using System.IO;
using System.Xml.Serialization;

namespace XmlSerializerMultipleFilesTest
{
    [Serializable]
    public class A
    {
        public int Value
        { get; set; }
    }

    [Serializable]
    public class B
    {
        public double Value
        { get; set; }
    }

    [Serializable]
    public class C
    {
        public string Value
        { get; set; }
    }

    [Serializable]
    public class AB
    {
        public A A
        { get; set; }
        public B B
        { get; set; }
    }

    [Serializable]
    public class BC
    {
        public B B
        { get; set; }
        public C C
        { get; set; }
    }

    class Program
    {
        public static void Serialize<T>(T data, string filePath)
        {
            using (var writer = new StreamWriter(filePath))
            {
                var xmlSerializer = new XmlSerializer(typeof(T));
                xmlSerializer.Serialize(writer, data);
            }
        }
        public static T Deserialize<T>(string filePath)
        {
            using (var reader = new StreamReader(filePath))
            {
                var xmlSerializer = new XmlSerializer(typeof(T));
                return (T)xmlSerializer.Deserialize(reader);
            }
        }

        static void Main(string[] args)
        {
            const string fileNameA = @"A.xml";
            const string fileNameB = @"B.xml";
            const string fileNameC = @"C.xml";

            const string fileNameAB = @"AB.xml";
            const string fileNameBC = @"BC.xml";

            var a = new A(){ Value = 42 };
            var b = new B(){ Value = Math.PI };
            var c = new C(){ Value = "Something rotten" };

            Serialize(a, fileNameA);
            Serialize(b, fileNameB);
            Serialize(c, fileNameC);

            // How can AB and BC be deserialized from single 
            // files which include two of the A, B or C files.
            // Using ideally something like:
            var ab = Deserialize<AB>(fileNameAB);
            var bc = Deserialize<BC>(fileNameBC);
            // That is, so that A, B, C xml file 
            // contents are shared across these two
        }
    }
}

Thus, the A, B, C files contain the following:

A.xml:

<?xml version="1.0" encoding="utf-8"?>
<A xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"&gt;
  <Value>42</Value>
</A>

B.xml:

<?xml version="1.0" encoding="utf-8"?>
<B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"&gt;
  <Value>3.1415926535897931</Value>
</B>

C.xml:

<?xml version="1.0" encoding="utf-8"?>
<C xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"&gt;
  <Value>Something rotten</Value>
</C>

And then the "parent" XML files would contain a XML include file of some sort (I have not been able to find anything like this), such as:

AB.xml:

<?xml version="1.0" encoding="utf-8"?>
<AB xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"&gt;
  <A include="A.xml"/>
  <B include="B.xml"/>
</AB>

BC.xml:

<?xml version="1.0" encoding="utf-8"?>
<BC xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"&gt;
  <B include="B.xml"/>
  <C include="C.xml"/>
</BC>

Of course, I guess this can be solved by implementing IXmlSerializer for AB and BC, but I was hoping there was an easier solution or a generic solution with which classes themselves only need the [Serializable] attribute and nothing else. That is, the split into multiple files is XML only and handled by XmlSerializer itself or a custom generic serializer on top of this.

I know this should be somewhat possible with app.config (as in http://stackoverflow.com/questions/480538/use-xml-includes-or-config-references-in-app-config-to-include-other-config-files), but I would prefer a solution based on XmlSerializer.

Thanks.

A: 

The short answer is yes, it's possible without implementing IXmlSerializer. But it's really ugly. Probably uglier than implementing IXmlSerializer. Check this out to get started. It involves running sgen.exe to generate the XmlSerializationWriter and XmlSerializationReader that is generated when you create an XmlSerializer. Then you modify the output from sgen.exe. Not fun. Not fun at all. But possible.

fre0n