英文:
IXmlSerializable ignores other properties during deserilization
问题
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>
英文:
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>
答案1
得分: 0
解决,需要再次调用 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();
}
英文:
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();
}
答案2
得分: 0
要解决这个问题,您需要修改ReadXml方法:
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(); // 读取“Name”的结束元素
reader.ReadEndElement(); // 读取当前对象的结束元素
}
英文:
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
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论