Added the XmlFormatWriter/Reader
diff --git a/src/ProtocolBuffers.Test/CompatTests/BinaryCompatibilityTests.cs b/src/ProtocolBuffers.Test/CompatTests/BinaryCompatibilityTests.cs
index fe8a1e3..c5b78bc 100644
--- a/src/ProtocolBuffers.Test/CompatTests/BinaryCompatibilityTests.cs
+++ b/src/ProtocolBuffers.Test/CompatTests/BinaryCompatibilityTests.cs
@@ -6,8 +6,6 @@
     [TestFixture]

     public class BinaryCompatibilityTests : CompatibilityTests

     {

-        protected override string TestName { get { return "binary"; } }

-

         protected override object SerializeMessage<TMessage, TBuilder>(TMessage message)

         {

             byte[] bresult = message.ToByteArray();

diff --git a/src/ProtocolBuffers.Test/CompatTests/CompatibilityTests.cs b/src/ProtocolBuffers.Test/CompatTests/CompatibilityTests.cs
index 5ce069b..49c5629 100644
--- a/src/ProtocolBuffers.Test/CompatTests/CompatibilityTests.cs
+++ b/src/ProtocolBuffers.Test/CompatTests/CompatibilityTests.cs
@@ -6,7 +6,6 @@
 {

     public abstract class CompatibilityTests

     {

-        protected abstract string TestName { get; }

         protected abstract object SerializeMessage<TMessage, TBuilder>(TMessage message)

             where TMessage : IMessageLite<TMessage, TBuilder>

             where TBuilder : IBuilderLite<TMessage, TBuilder>;

diff --git a/src/ProtocolBuffers.Test/CompatTests/TextCompatibilityTests.cs b/src/ProtocolBuffers.Test/CompatTests/TextCompatibilityTests.cs
index 83f19ae..0b57535 100644
--- a/src/ProtocolBuffers.Test/CompatTests/TextCompatibilityTests.cs
+++ b/src/ProtocolBuffers.Test/CompatTests/TextCompatibilityTests.cs
@@ -7,8 +7,6 @@
     [TestFixture]

     public class TextCompatibilityTests : CompatibilityTests

     {

-        protected override string TestName { get { return "text"; } }

-

         protected override object SerializeMessage<TMessage, TBuilder>(TMessage message)

         {

             StringWriter text = new StringWriter();

diff --git a/src/ProtocolBuffers.Test/CompatTests/XmlCompatibilityTests.cs b/src/ProtocolBuffers.Test/CompatTests/XmlCompatibilityTests.cs
new file mode 100644
index 0000000..e204200
--- /dev/null
+++ b/src/ProtocolBuffers.Test/CompatTests/XmlCompatibilityTests.cs
@@ -0,0 +1,24 @@
+using System.IO;

+using Google.ProtocolBuffers.Serialization;

+using NUnit.Framework;

+

+namespace Google.ProtocolBuffers.CompatTests

+{

+    [TestFixture]

+    public class XmlCompatibilityTests : CompatibilityTests

+    {

+        protected override object SerializeMessage<TMessage, TBuilder>(TMessage message)

+        {

+            StringWriter text = new StringWriter();

+            XmlFormatWriter writer = new XmlFormatWriter(text);

+            writer.WriteMessage("root", message);

+            return text.ToString();

+        }

+

+        protected override TBuilder DeerializeMessage<TMessage, TBuilder>(object message, TBuilder builder, ExtensionRegistry registry)

+        {

+            XmlFormatReader reader = new XmlFormatReader((string)message);

+            return reader.Merge("root", builder, registry);

+        }

+    }

+}
\ No newline at end of file
diff --git a/src/ProtocolBuffers.Test/ProtocolBuffers.Test.csproj b/src/ProtocolBuffers.Test/ProtocolBuffers.Test.csproj
index 06dda01..39b4026 100644
--- a/src/ProtocolBuffers.Test/ProtocolBuffers.Test.csproj
+++ b/src/ProtocolBuffers.Test/ProtocolBuffers.Test.csproj
@@ -83,6 +83,7 @@
       <DependentUpon>TestResources.resx</DependentUpon>

     </Compile>

     <Compile Include="CompatTests\TextCompatibilityTests.cs" />

+    <Compile Include="CompatTests\XmlCompatibilityTests.cs" />

     <Compile Include="CSharpOptionsTest.cs" />

     <Compile Include="DescriptorsTest.cs" />

     <Compile Include="Descriptors\MessageDescriptorTest.cs" />

@@ -114,6 +115,7 @@
     <Compile Include="TestProtos\UnitTestXmlSerializerTestProtoFile.cs" />

     <Compile Include="TestRpcGenerator.cs" />

     <Compile Include="TestUtil.cs" />

+    <Compile Include="TestWriterFormatXml.cs" />

     <Compile Include="TextFormatTest.cs" />

     <Compile Include="UnknownFieldSetTest.cs" />

     <Compile Include="WireFormatTest.cs" />

diff --git a/src/ProtocolBuffers.Test/TestWriterFormatXml.cs b/src/ProtocolBuffers.Test/TestWriterFormatXml.cs
new file mode 100644
index 0000000..a2def5e
--- /dev/null
+++ b/src/ProtocolBuffers.Test/TestWriterFormatXml.cs
@@ -0,0 +1,308 @@
+using System;

+using System.Collections.Generic;

+using System.IO;

+using System.Text;

+using System.Xml;

+using Google.ProtocolBuffers.Serialization;

+using NUnit.Framework;

+using Google.ProtocolBuffers.TestProtos;

+

+namespace Google.ProtocolBuffers

+{

+    [TestFixture]

+    public class TestWriterFormatXml

+    {

+        [Test]

+        public void TestEmptyMessage()

+        {

+            TestXmlChild message = TestXmlChild.CreateBuilder()

+                .Build();

+

+            StringWriter sw = new StringWriter();

+            XmlTextWriter xw = new XmlTextWriter(sw);

+

+            //When we call message.WriteTo, we are responsible for the root element

+            xw.WriteStartElement("root");

+            message.WriteTo(new XmlFormatWriter(xw));

+            xw.WriteEndElement();

+            xw.Flush();

+

+            string xml = sw.ToString();

+            XmlFormatReader rdr = new XmlFormatReader(xml);

+            TestXmlChild copy = rdr.Merge(TestXmlChild.CreateBuilder()).Build();

+            Assert.AreEqual(message, copy);

+        }

+        [Test]

+        public void TestRepeatedField()

+        {

+            TestXmlChild message = TestXmlChild.CreateBuilder()

+                .AddOptions(EnumOptions.ONE)

+                .AddOptions(EnumOptions.TWO)

+                .Build();

+

+            //Allow the writer to write the root element

+            StringWriter sw = new StringWriter();

+            new XmlFormatWriter(sw).WriteMessage("root", message);

+

+            string xml = sw.ToString();

+            XmlFormatReader rdr = new XmlFormatReader(xml);

+            TestXmlChild copy = rdr.Merge(TestXmlChild.CreateBuilder()).Build();

+            Assert.AreEqual(message, copy);

+        }

+        [Test]

+        public void TestNestedEmptyMessage()

+        {

+            TestXmlMessage message = TestXmlMessage.CreateBuilder()

+                .SetChild(TestXmlChild.CreateBuilder().Build())

+                .Build();

+

+            StringWriter sw = new StringWriter();

+            new XmlFormatWriter(sw).WriteMessage("root", message);

+

+            string xml = sw.ToString();

+            XmlFormatReader rdr = new XmlFormatReader(xml);

+            TestXmlMessage copy = rdr.Merge(TestXmlMessage.CreateBuilder()).Build();

+            Assert.AreEqual(message, copy);

+        }

+        [Test]

+        public void TestNestedMessage()

+        {

+            TestXmlMessage message = TestXmlMessage.CreateBuilder()

+                .SetChild(TestXmlChild.CreateBuilder().AddOptions(EnumOptions.TWO).Build())

+                .Build();

+

+            StringWriter sw = new StringWriter();

+            new XmlFormatWriter(sw).WriteMessage("root", message);

+

+            string xml = sw.ToString();

+            XmlFormatReader rdr = new XmlFormatReader(xml);

+            TestXmlMessage copy = rdr.Merge(TestXmlMessage.CreateBuilder()).Build();

+            Assert.AreEqual(message, copy);

+        }

+        [Test]

+        public void TestBooleanTypes()

+        {

+            TestXmlMessage message = TestXmlMessage.CreateBuilder()

+                .SetValid(true)

+                .Build();

+

+            StringWriter sw = new StringWriter();

+            new XmlFormatWriter(sw).WriteMessage("root", message);

+

+            string xml = sw.ToString();

+            XmlFormatReader rdr = new XmlFormatReader(xml);

+            TestXmlMessage copy = rdr.Merge(TestXmlMessage.CreateBuilder()).Build();

+            Assert.AreEqual(message, copy);

+        }

+        [Test]

+        public void TestFullMessage()

+        {

+            TestXmlMessage message = TestXmlMessage.CreateBuilder()

+                .SetValid(true)

+                .SetText("text")

+                .AddTextlines("a")

+                .AddTextlines("b")

+                .AddTextlines("c")

+                .SetNumber(0x1010101010)

+                .AddNumbers(1)

+                .AddNumbers(2)

+                .AddNumbers(3)

+                .SetChild(TestXmlChild.CreateBuilder().AddOptions(EnumOptions.ONE).SetBinary(ByteString.CopyFrom(new byte[1])))

+                .AddChildren(TestXmlMessage.Types.Children.CreateBuilder().AddOptions(EnumOptions.TWO).SetBinary(ByteString.CopyFrom(new byte[2])))

+                .AddChildren(TestXmlMessage.Types.Children.CreateBuilder().AddOptions(EnumOptions.THREE).SetBinary(ByteString.CopyFrom(new byte[3])))

+                .Build();

+

+            StringWriter sw = new StringWriter();

+            new XmlFormatWriter(sw).WriteMessage("root", message);

+

+            string xml = sw.ToString();

+

+            XmlFormatReader rdr = new XmlFormatReader(xml);

+            TestXmlMessage copy = rdr.Merge(TestXmlMessage.CreateBuilder()).Build();

+            Assert.AreEqual(message, copy);

+        }

+        [Test]

+        public void TestFullMessageWithRichTypes()

+        {

+            TestXmlMessage message = TestXmlMessage.CreateBuilder()

+                .SetValid(true)

+                .SetText("text")

+                .AddTextlines("a")

+                .AddTextlines("b")

+                .AddTextlines("c")

+                .SetNumber(0x1010101010)

+                .AddNumbers(1)

+                .AddNumbers(2)

+                .AddNumbers(3)

+                .SetChild(TestXmlChild.CreateBuilder().AddOptions(EnumOptions.ONE).SetBinary(ByteString.CopyFrom(new byte[1])))

+                .AddChildren(TestXmlMessage.Types.Children.CreateBuilder().AddOptions(EnumOptions.TWO).SetBinary(ByteString.CopyFrom(new byte[2])))

+                .AddChildren(TestXmlMessage.Types.Children.CreateBuilder().AddOptions(EnumOptions.THREE).SetBinary(ByteString.CopyFrom(new byte[3])))

+                .Build();

+

+            StringWriter sw = new StringWriter();

+            new XmlFormatWriter(sw) 

+            {

+                Options = XmlWriterOptions.OutputNestedArrays | XmlWriterOptions.OutputEnumValues

+            }.WriteMessage("root", message);

+

+            string xml = sw.ToString();

+

+            XmlFormatReader rdr = new XmlFormatReader(xml);

+            rdr.Options = XmlReaderOptions.ReadNestedArrays;

+            TestXmlMessage copy = rdr.Merge(TestXmlMessage.CreateBuilder()).Build();

+            Assert.AreEqual(message, copy);

+        }

+        [Test]

+        public void TestFullMessageWithUnknownFields()

+        {

+            TestXmlMessage origial = TestXmlMessage.CreateBuilder()

+                    .SetValid(true)

+                    .SetText("text")

+                    .AddTextlines("a")

+                    .AddTextlines("b")

+                    .AddTextlines("c")

+                    .SetNumber(0x1010101010)

+                    .AddNumbers(1)

+                    .AddNumbers(2)

+                    .AddNumbers(3)

+                    .SetChild(TestXmlChild.CreateBuilder().AddOptions(EnumOptions.ONE).SetBinary(ByteString.CopyFrom(new byte[1])))

+                    .AddChildren(TestXmlMessage.Types.Children.CreateBuilder().AddOptions(EnumOptions.TWO).SetBinary(ByteString.CopyFrom(new byte[2])))

+                    .AddChildren(TestXmlMessage.Types.Children.CreateBuilder().AddOptions(EnumOptions.THREE).SetBinary(ByteString.CopyFrom(new byte[3])))

+                .Build();

+            TestXmlNoFields message = TestXmlNoFields.CreateBuilder().MergeFrom(origial.ToByteArray()).Build();

+

+            Assert.AreEqual(0, message.AllFields.Count);

+

+            StringWriter sw = new StringWriter();

+            new XmlFormatWriter(sw)

+            {

+                Options = XmlWriterOptions.OutputNestedArrays | XmlWriterOptions.OutputEnumValues

+            }.WriteMessage("root", message);

+

+            string xml = sw.ToString();

+

+            using (XmlReader x = XmlReader.Create(new StringReader(xml)))

+            {

+                x.MoveToContent();

+                Assert.AreEqual(XmlNodeType.Element, x.NodeType);

+                //should always be empty

+                Assert.IsTrue(x.IsEmptyElement ||

+                    (x.Read() && x.NodeType == XmlNodeType.EndElement)

+                    );

+            }

+

+            XmlFormatReader rdr = new XmlFormatReader(xml);

+            rdr.Options = XmlReaderOptions.ReadNestedArrays;

+            TestXmlMessage copy = rdr.Merge(TestXmlMessage.CreateBuilder()).Build();

+            Assert.AreEqual(TestXmlMessage.DefaultInstance, copy);

+        }

+        [Test]

+        public void TestMessageWithXmlText()

+        {

+            TestXmlMessage message = TestXmlMessage.CreateBuilder()

+                .SetText("<text>").Build();

+

+            StringWriter sw = new StringWriter();

+            new XmlFormatWriter(sw).WriteMessage("root", message);

+

+            string xml = sw.ToString();

+

+            XmlFormatReader rdr = new XmlFormatReader(xml);

+            TestXmlMessage copy = rdr.Merge(TestXmlMessage.CreateBuilder()).Build();

+            Assert.AreEqual(message, copy);

+        }

+        [Test]

+        public void TestXmlWithWhitespace()

+        {

+            TestXmlMessage message = TestXmlMessage.CreateBuilder()

+                .SetText(" \t <- leading space and trailing -> \r\n\t").Build();

+

+            StringWriter sw = new StringWriter();

+            new XmlFormatWriter(sw).WriteMessage("root", message);

+

+            string xml = sw.ToString();

+

+            XmlFormatReader rdr = new XmlFormatReader(xml);

+            TestXmlMessage copy = rdr.Merge(TestXmlMessage.CreateBuilder()).Build();

+            Assert.AreEqual(message, copy);

+        }

+        [Test]

+        public void TestXmlWithExtensionText()

+        {

+            TestXmlMessage message = TestXmlMessage.CreateBuilder()

+                .SetExtension(UnitTestXmlSerializerTestProtoFile.ExtensionText, " extension text value ! ")

+                .Build();

+

+            StringWriter sw = new StringWriter();

+            new XmlFormatWriter(sw).WriteMessage("root", message);

+

+            string xml = sw.ToString();

+

+            ExtensionRegistry registry = ExtensionRegistry.CreateInstance();

+            UnitTestXmlSerializerTestProtoFile.RegisterAllExtensions(registry);

+

+            XmlFormatReader rdr = new XmlFormatReader(xml);

+            TestXmlMessage copy = rdr.Merge(TestXmlMessage.CreateBuilder(), registry).Build();

+            Assert.AreEqual(message, copy);

+        }

+        [Test]

+        public void TestXmlWithExtensionMessage()

+        {

+            TestXmlMessage message = TestXmlMessage.CreateBuilder()

+                .SetExtension(UnitTestXmlSerializerTestProtoFile.ExtensionMessage,

+                new TestXmlExtension.Builder().SetNumber(42).Build()).Build();

+

+            StringWriter sw = new StringWriter();

+            new XmlFormatWriter(sw).WriteMessage("root", message);

+

+            string xml = sw.ToString();

+

+            ExtensionRegistry registry = ExtensionRegistry.CreateInstance();

+            UnitTestXmlSerializerTestProtoFile.RegisterAllExtensions(registry);

+

+            XmlFormatReader rdr = new XmlFormatReader(xml);

+            TestXmlMessage copy = rdr.Merge(TestXmlMessage.CreateBuilder(), registry).Build();

+            Assert.AreEqual(message, copy);

+        }

+        [Test]

+        public void TestXmlWithExtensionArray()

+        {

+            TestXmlMessage message = TestXmlMessage.CreateBuilder()

+                .AddExtension(UnitTestXmlSerializerTestProtoFile.ExtensionNumber, 100)

+                .AddExtension(UnitTestXmlSerializerTestProtoFile.ExtensionNumber, 101)

+                .AddExtension(UnitTestXmlSerializerTestProtoFile.ExtensionNumber, 102)

+                .Build();

+

+            StringWriter sw = new StringWriter();

+            new XmlFormatWriter(sw).WriteMessage("root", message);

+

+            string xml = sw.ToString();

+

+            ExtensionRegistry registry = ExtensionRegistry.CreateInstance();

+            UnitTestXmlSerializerTestProtoFile.RegisterAllExtensions(registry);

+

+            XmlFormatReader rdr = new XmlFormatReader(xml);

+            TestXmlMessage copy = rdr.Merge(TestXmlMessage.CreateBuilder(), registry).Build();

+            Assert.AreEqual(message, copy);

+        }

+        [Test]

+        public void TestXmlWithExtensionEnum()

+        {

+            TestXmlMessage message = TestXmlMessage.CreateBuilder()

+                .SetExtension(UnitTestXmlSerializerTestProtoFile.ExtensionEnum, EnumOptions.ONE)

+                .Build();

+

+            StringWriter sw = new StringWriter();

+            new XmlFormatWriter(sw).WriteMessage("root", message);

+

+            string xml = sw.ToString();

+

+            ExtensionRegistry registry = ExtensionRegistry.CreateInstance();

+            UnitTestXmlSerializerTestProtoFile.RegisterAllExtensions(registry);

+

+            XmlFormatReader rdr = new XmlFormatReader(xml);

+            TestXmlMessage copy = rdr.Merge(TestXmlMessage.CreateBuilder(), registry).Build();

+            Assert.AreEqual(message, copy);

+        }

+    }

+}