0

If I deserialize XML which include a comment-element and it is deserialize to a class with ordered properties I get the exception:

There is an error in XML document (4, 25). Unable to cast object of type 'System.Xml.XmlElement' to type 'System.Xml.XmlComment'.

This is the XML:

<?xml version="1.0" encoding="utf-8"?>
<ROOT>
    <!--Hello World-->
    <Field1>Hello1</Field1>
</ROOT>

Why does the XmlSerializer try to parse the <Field1> element as a XmlComment when the field in the class is marked with the attribute '[XmlElement]'?
(this only happens when using ordered elements!).

The C# class:

public class oFoo1
{
    [XmlAnyElement("Foo_Comment", Order = 0)]
    public XmlComment? FooComment { get; set; }

    [XmlElement(Order = 1)]
    public string? Field1;
            
    public oFoo1() {}
}

Code to instantiate object and serialization:

public static void Main()
{
    // Instantiate object
    var CFG = new oFoo1()
    {
        FooComment = new XmlDocument().CreateComment("Hello World"),
        Field1 = "Hello1",
    };

    // Serialize object
    Serialize_to_File<oFoo1>(Obj: CFG, Path: @"c:\temp\test.xml");

    // Deserialize object (will print exception)
    var Obj = Serialize_to_Object<oFoo1>(Path: @"c:\temp\test.xml");
}

public static void Serialize_to_File<T>(T Obj, string Path)
{
    XmlSerializerNamespaces NS = new XmlSerializerNamespaces();
    NS.Add(prefix:"", ns: "");
    XmlWriterSettings XWS = new XmlWriterSettings() {Indent = true, IndentChars = "\t"};

    using (XmlWriter XW = XmlWriter.Create(outputFileName: Path, settings: XWS))
    {
        XmlSerializer X = new XmlSerializer(typeof(T), root: new XmlRootAttribute("ROOT"));
        X.Serialize(xmlWriter: XW, o: Obj, namespaces: NS);
    }
}

public static object? Serialize_to_Object<T>(string Path)
{
    try
    {
        T? Obj;

        using (XmlReader XR = XmlReader.Create(inputUri: Path))
        {
            var XS = new XmlSerializer(typeof(T), new XmlRootAttribute("ROOT"));
            Obj = (T?)XS.Deserialize(XR);
        }

        return Obj;
    }
    catch (Exception Ex)
    {
        Console.WriteLine(
            Ex.Message + "\n" + 
            (Ex.InnerException ?? new Exception()).Message
            );
        return null;
    }
}

UPDATE: Even though the question and problem (bug) stands, and that's why I don't delete it, the purpose is not after some thoughts. The purpose was to create a "template" of an application config-file with build-in documentation and ordering of comments and properties is advantageous. But user might change the order of the properties in the config-file themselves (which is expected to be OK in a xml file) and that will break deserialization anyway, so ordered elements isn't feasible after all. To archive my goal I guess I have to create a copy of the config-class with order-attributes and serialize that when creating the template-config-file, and then use the "real" config-class for deserialization.

MrCalvin
  • 1,675
  • 1
  • 19
  • 27

0 Answers0