0

I have a class implements IXmlSerializable, after ReadXml been called, the deserialization process returns and ignore other properties. The xml file is completed, but when deserial it, only the first property "B" is loaded, "List" and "List1" are empty. Is there anything wrong with the ReadXml or WriteXml?

[Serializable]
    public class B : IXmlSerializable
    {
        private List<string> name;

        public List<string> Name { get => name; set => name = value; }

        public B() {
            name = new List<string>();
            name.Add("1");
            name.Add("2");
        }

        public XmlSchema? GetSchema()
        {
            return null;
        }

        public void ReadXml(XmlReader reader)
        {
            reader.ReadStartElement();
            Name.Clear();
            int depth = reader.Depth;
            reader.ReadStartElement("Name");
            while (reader.Depth == depth + 1)
            {
                var element = reader.ReadElementString("Str");
                name.Add(element);
            }

            if (reader.Name.Equals("Name"))
                reader.ReadEndElement();
        }

        public void WriteXml(XmlWriter writer)
        {
            writer.WriteStartElement("Name");
            for (int i = 0; i < name.Count; i++)
            {
                writer.WriteStartElement("Str");
                writer.WriteValue(name[i]);
                writer.WriteEndElement();
            }
            writer.WriteEndElement();
        }
    }

public class Config
    {
        private B b = new B();
        private List<B> list = new List<B>();
        private List<B> list1 = new List<B>();

        public B B { get => b; set => b = value; }

        [XmlArrayItem(Type = typeof(B))]
        public List<B> List { get => list; set => list = value; }

        [XmlArrayItem(Type = typeof(B))]
        public List<B> List1 { get => list1; set => list1 = value; }
    }

public class Helper
    {
        public static object LoadXML(string fileName, Type objectType, Type[] extraTypes)
        {
            Object obj = null;

            if (File.Exists(fileName))
            {
                XmlReaderSettings settings = new XmlReaderSettings();
                settings.IgnoreComments = true;
                settings.IgnoreWhitespace = true;
                settings.IgnoreProcessingInstructions = true;

                using (XmlReader reader = XmlReader.Create(fileName, settings))
                {
                    XmlSerializer ser = new XmlSerializer(objectType, extraTypes);
                    obj = ser.Deserialize(reader);
                }
            }
            return obj;
        }

        public static void SaveXML(object obj, string fileName, Type[] extraTypes)
        {
            XmlWriterSettings settings = new XmlWriterSettings();
            settings.Indent = true;
            settings.IndentChars = ("\t");

            using (XmlWriter writer = XmlWriter.Create(fileName, settings))
            {
                XmlSerializer ser = new XmlSerializer(obj.GetType(), extraTypes);
                ser.Serialize(writer, obj);
            }
        }
    }

    public class Program
    {
        public static void Main()
        {
            var config = new Config();
            config.List.Add(new B());
            config.List.Add(new B());
            config.List1.Add(new B());
            config.List1.Add(new B());

            List<Type> list = new List<Type>();
            list.Add(typeof(B));

            Helper.SaveXML(config, "1.xml", list.ToArray());

            var loaded = Helper.LoadXML("1.xml", typeof(Config), list.ToArray()) as Config;
        }
    }
<?xml version="1.0" encoding="utf-8"?>
<Config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <B>
        <Name>
            <Str>1</Str>
            <Str>2</Str>
        </Name>
    </B>
    <List>
        <B>
            <Name>
                <Str>1</Str>
                <Str>2</Str>
            </Name>
        </B>
        <B>
            <Name>
                <Str>1</Str>
                <Str>2</Str>
            </Name>
        </B>
    </List>
    <List1>
        <B>
            <Name>
                <Str>1</Str>
                <Str>2</Str>
            </Name>
        </B>
        <B>
            <Name>
                <Str>1</Str>
                <Str>2</Str>
            </Name>
        </B>
    </List1>
</Config>
Lamp
  • 302
  • 1
  • 10

2 Answers2

0

Sloved, need one more ReadEndElement

public void ReadXml(XmlReader reader)
        {
            reader.ReadStartElement();
            Name.Clear();
            int depth = reader.Depth;
            reader.ReadStartElement("Name");
            while (reader.Depth == depth + 1)
            {
                var element = reader.ReadElementString("Str");
                name.Add(element);
            }

            if (reader.Name.Equals("Name"))
                reader.ReadEndElement();
            reader.ReadEndElement();
        }
Lamp
  • 302
  • 1
  • 10
0

To fix this issue, you need to modify the ReadXml method

public void ReadXml(XmlReader reader)
{
    reader.ReadStartElement();
    Name.Clear();
    int depth = reader.Depth;
    reader.ReadStartElement("Name");
    while (reader.Depth >= depth + 1)
    {
        if (reader.Name == "Str")
        {
            var element = reader.ReadElementString();
            Name.Add(element);
        }
        else
        {
            reader.Read();
        }
    }
    reader.ReadEndElement(); // Read the end element for "Name"
    reader.ReadEndElement(); // Read the end element for the current object
}
Krishna Varma
  • 4,238
  • 2
  • 10
  • 25