22 September 2005

Loading Xml Serialization Object Graph

A memo on using XmlSerializer.Serialize and loading the object graph:
1) use default XmlTextWriter
2) provide StringWriter to control the xml output format
3) use MemoryStream to control encoding
4) by lazy, use Console.Out to check the output on screen

There are quite a few ways to stream out the XmlSerializer marshalling result depends on the need.

How XmlSerializer.Serialize works?


1. XmlSerializer xs = new XmlSerializer(typeof(Foo));
2. xs.Serialize(..., aFoo);

On excuting the second line, our serializer then tries to serialize aFoo to Foo type. If Foo implements IXmlSerializable, it will ingore all public properties and just execute WriterXml that Foo implemented.
By default, serializer passes an object of XmlTextWriter to WriterXml. In your WriterXml implementation, you should never close the Writer. This should be left to the caller (XmlSerializer in our case).

How to serialize an object and load the marshalled result (object graph)?
The most common way is use the default XmlTextWriter
However, the xml document gererated is nicely formatted - i.e. indented. If a custom control over the format is needed, you need to passed your XmlTextWriter object to Serializer

1. XmlSerializer xs = new XmlSerializer(typeof(Foo));
2. using (StringWriter sw = new StringWriter())
3. {
4. XmlTextWriter xtwriter =new XmlTextWriter(sw);
5. xtwriter.Formatting = Formatting.None;
6. xs.Serialize(xtwriter, item.Reviews);
7. Console.WriteLine(sw.ToString());
8. }

As seen, we have a control over on the xml doc layout by specified Formatting style.
Not everthing can be controlled if use StringWriter though. It is Unicode base, so unless you override (or hijack?) StringWriter, you will always see utf-16 encoding

To specify which Encoding style to use, you need to use MemoryStream instead

1. XmlSerializer xs = new XmlSerializer(typeof(Foo));
2. using (MemoryStream ms = new MemoryStream())
3. {
4. XmlTextWriter xtwriter =new XmlTextWriter(ms, Encoding.UTF8);
5. xtwriter.Formatting = Formatting.None;
6. xs.Serialize(xtwriter, aFoo);
7. xtwriter.Flush();
8. ms.Position = 0;
9. XmlDocument doc = new XmlDocument();
10. doc.Load(new MemoryStream(ms.GetBuffer()) );
11. }

And simplified version without encoding or style:

1. XmlSerializer xs = new XmlSerializer(typeof(Foo));
2. using (MemoryStream ms = new MemoryStream())
3. {
4. xs.Serialize(ms, item.Reviews);
5. XmlDocument doc = new XmlDocument();
6. doc.Load(new MemoryStream(ms.GetBuffer()) );
7. Console.WriteLine(doc.OuterXml);
8. }

And finally, just be lazy - use Console.Out gives you a quick peek on what is produced:

1. XmlSerializer xs = new XmlSerializer(typeof(Foo));
2. xs.Serialize(Console.Out, aFoo);

No comments: