Search code examples
c#xmlbond

Deserialize xml using Bond throws System.IO.InvalidDataException : Unexpected node type


I played a little with Bond using this code:

using System;
using System.IO;
using System.Text;
using System.Xml;
using Bond;
using Bond.Protocols;
using NUnit.Framework;

public class Sandbox
{
    [Test]
    public void RoundtripWithSchema()
    {
        var sb = new StringBuilder();
        var source = new WithSchema { Value = 1 };

        using (XmlWriter xmlWriter = XmlWriter.Create(sb))
        {
            var writer = new SimpleXmlWriter(xmlWriter);
            Serialize.To(writer, source);
        }
        var xml = sb.ToString();
        Console.Write(xml);
        Console.WriteLine();

        using (var xmlReader = XmlReader.Create(new StringReader(xml)))
        {
            var reader = new SimpleXmlReader(xmlReader);
            var roundtripped = Deserialize<WithSchema>.From(reader); // System.IO.InvalidDataException : Unexpected node type
            Assert.AreEqual(source.Value, roundtripped.Value);
        }
    }

    [Test]
    public void RoundtripUsingSerializerWithSchema()
    {
        var sb = new StringBuilder();
        var source = new WithSchema { Value = 1 };

        using (XmlWriter xmlWriter = XmlWriter.Create(sb))
        {
            var writer = new SimpleXmlWriter(xmlWriter);
            var serializer = new Serializer<SimpleXmlWriter>(typeof(WithSchema));
            serializer.Serialize(source, writer);
        }
        var xml = sb.ToString();
        Console.Write(xml);
        Console.WriteLine();

        using (var xmlReader = XmlReader.Create(new StringReader(xml)))
        {
            var reader = new SimpleXmlReader(xmlReader);
            var serializer = new Deserializer<SimpleXmlReader>(typeof(WithSchema));
            var roundtripped = serializer.Deserialize<WithSchema>(reader); // System.IO.InvalidDataException : Unexpected node type
            Assert.AreEqual(source.Value, roundtripped.Value);
        }
    }
}

[Schema]
public class WithSchema
{
    [Id(0)]
    public int Value { get; set; }
}

Both samples output the expected xml:

<?xml version="1.0" encoding="utf-16"?>
<WithSchema>
    <Value>1</Value>
</WithSchema>

Both fail when deserializing throwing System.IO.InvalidDataException : Unexpected node type

Don't know where to look for the bug really, suggestions?


Solution

  • The Bond SimpleXmlReader is having trouble with the <?xml version="1.0" encoding="utf-16"?> line. If you leave this out when serializing, you can deserialize without a problem.

    Try something like this

    using (XmlWriter xmlWriter = XmlWriter.Create(sb, new XmlWriterSettings { OmitXmlDeclaration = true }))
    {
        var writer = new SimpleXmlWriter(xmlWriter);
        Serialize.To(writer, source);
    }
    

    My guess is that XmlNodeType.XmlDeclaration probably needs to be added to the IgnoredTokens set in Bond's SimpleXmlParser.

    Bond versions later than v4.0.1 will have this issue (Bond issue #112 on GitHub) fixed.

    Inspiration for this answer came from the Bond simple_xml sample.