IXmlSerializable 在反序列化过程中忽略其他属性

huangapple go评论68阅读模式
英文:

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&lt;string&gt; name;
public List&lt;string&gt; Name { get =&gt; name; set =&gt; name = value; }
public B() {
name = new List&lt;string&gt;();
name.Add(&quot;1&quot;);
name.Add(&quot;2&quot;);
}
public XmlSchema? GetSchema()
{
return null;
}
public void ReadXml(XmlReader reader)
{
reader.ReadStartElement();
Name.Clear();
int depth = reader.Depth;
reader.ReadStartElement(&quot;Name&quot;);
while (reader.Depth == depth + 1)
{
var element = reader.ReadElementString(&quot;Str&quot;);
name.Add(element);
}
if (reader.Name.Equals(&quot;Name&quot;))
reader.ReadEndElement();
}
public void WriteXml(XmlWriter writer)
{
writer.WriteStartElement(&quot;Name&quot;);
for (int i = 0; i &lt; name.Count; i++)
{
writer.WriteStartElement(&quot;Str&quot;);
writer.WriteValue(name[i]);
writer.WriteEndElement();
}
writer.WriteEndElement();
}
}
public class Config
{
private B b = new B();
private List&lt;B&gt; list = new List&lt;B&gt;();
private List&lt;B&gt; list1 = new List&lt;B&gt;();
public B B { get =&gt; b; set =&gt; b = value; }
[XmlArrayItem(Type = typeof(B))]
public List&lt;B&gt; List { get =&gt; list; set =&gt; list = value; }
[XmlArrayItem(Type = typeof(B))]
public List&lt;B&gt; List1 { get =&gt; list1; set =&gt; 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 = (&quot;\t&quot;);
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&lt;Type&gt; list = new List&lt;Type&gt;();
list.Add(typeof(B));
Helper.SaveXML(config, &quot;1.xml&quot;, list.ToArray());
var loaded = Helper.LoadXML(&quot;1.xml&quot;, typeof(Config), list.ToArray()) as Config;
}
}
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;Config xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot; xmlns:xsd=&quot;http://www.w3.org/2001/XMLSchema&quot;&gt;
&lt;B&gt;
&lt;Name&gt;
&lt;Str&gt;1&lt;/Str&gt;
&lt;Str&gt;2&lt;/Str&gt;
&lt;/Name&gt;
&lt;/B&gt;
&lt;List&gt;
&lt;B&gt;
&lt;Name&gt;
&lt;Str&gt;1&lt;/Str&gt;
&lt;Str&gt;2&lt;/Str&gt;
&lt;/Name&gt;
&lt;/B&gt;
&lt;B&gt;
&lt;Name&gt;
&lt;Str&gt;1&lt;/Str&gt;
&lt;Str&gt;2&lt;/Str&gt;
&lt;/Name&gt;
&lt;/B&gt;
&lt;/List&gt;
&lt;List1&gt;
&lt;B&gt;
&lt;Name&gt;
&lt;Str&gt;1&lt;/Str&gt;
&lt;Str&gt;2&lt;/Str&gt;
&lt;/Name&gt;
&lt;/B&gt;
&lt;B&gt;
&lt;Name&gt;
&lt;Str&gt;1&lt;/Str&gt;
&lt;Str&gt;2&lt;/Str&gt;
&lt;/Name&gt;
&lt;/B&gt;
&lt;/List1&gt;
&lt;/Config&gt;

答案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(&quot;Name&quot;);
while (reader.Depth == depth + 1)
{
var element = reader.ReadElementString(&quot;Str&quot;);
name.Add(element);
}
if (reader.Name.Equals(&quot;Name&quot;))
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(&quot;Name&quot;);
while (reader.Depth &gt;= depth + 1)
{
if (reader.Name == &quot;Str&quot;)
{
var element = reader.ReadElementString();
Name.Add(element);
}
else
{
reader.Read();
}
}
reader.ReadEndElement(); // Read the end element for &quot;Name&quot;
reader.ReadEndElement(); // Read the end element for the current object
}

huangapple
  • 本文由 发表于 2023年6月5日 11:38:24
  • 转载请务必保留本文链接:https://go.coder-hub.com/76403374.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定