完全坚持这种XML反序列化

时间:2014-09-19 17:07:00

标签: c# xml serialization datacontractserializer

我不能为我的生活找出为什么我无法将我的XML反序列化为类实例。请参阅下面我尝试的两种方法(及其各自的错误消息)。

方法一:

    public static SkillCollection Deserialize(string path)
    {
        using (MemoryStream memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(Path.Combine(path, "Skills.xml"))))
        {
            SkillCollection skills = null;
            try
            {
                var serializer = new DataContractSerializer(typeof(SkillCollection));
                var reader = XmlDictionaryReader.CreateTextReader(memoryStream, Encoding.UTF8, new XmlDictionaryReaderQuotas(), null);
                skills = (SkillCollection)serializer.ReadObject(memoryStream);
            }
            catch (SerializationException ex)
            {
                Globals.Instance.ApplicationLogger.Log("The object graph could not be deserialized from the binary stream because of the following error: " + ex);
            }
            return skills;
        }
    }

这样称呼: Skills = SkillCollection.Deserialize(path);

错误: XmlException was thrown: UnexpectedEndOfFile


方法二:

    public static object Deserialize(string xml, Type toType)
    {
        Console.WriteLine("File exists? " + File.Exists(xml));
        using (MemoryStream memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(xml)))
        {
            XmlDictionaryReader reader = XmlDictionaryReader.CreateTextReader(memoryStream, Encoding.UTF8, new XmlDictionaryReaderQuotas(), null);
            DataContractSerializer serializer = new DataContractSerializer(toType);
            return serializer.ReadObject(reader);
        }
    }

这样称呼: Skills = (SkillCollection) SkillCollection.Deserialize(Path.Combine(path, "Skills.xml"), typeof(SkillCollection));

错误1: XmlException was thrown: "The data at the root level is invalid. Line 1, position 1."

错误2: SerializationException was thrown: "There was an error deserializing the object of type MagBot_FFXIV.SkillCollection. The data at the root level is invalid. Line 1, position 1."


我的XML:

<Skills>
  <Fire>
    <Cast>0.00</Cast>
    <ReCast>60.00</ReCast>
    <MPCost>0</MPCost>
    <Button>0</Button>
  </Fire>
  <Ice>
    <Cast>2.49</Cast>
    <ReCast>2.49</ReCast>
    <MPCost>9</MPCost>
    <Button>1</Button>
  </Ice>
</Skills>

万分感谢您的帮助。


更新

之前我曾经使用LINQ2XML,但在我的情况下它并没有帮助。请参阅我今天早些时候发布的这篇文章:XML to Dictionary to Instances of Custom Class


我的最终代码如下。完美运作,希望它能帮助其他人。

    public static object DataContractSerializer_Deserialize(string path, Type toType)
    {
        using (var sr = new FileStream(path, FileMode.Open))
        {
            SkillCollection p = null;
            var serializer = new DataContractSerializer(toType);
            var reader = XmlDictionaryReader.CreateTextReader(sr, new XmlDictionaryReaderQuotas());

            while (reader.Read())
            {
                switch (reader.NodeType)
                {
                    case XmlNodeType.Element:
                        if (serializer.IsStartObject(reader))
                        {
                            Console.WriteLine(@"Found the element");
                            p = (SkillCollection)serializer.ReadObject(reader);
                        }
                        Console.WriteLine(reader.Name);
                        break;
                }
            }

            return p;
        }
    }

备注:

  • 请记住,您的XML元素必须按照alpha顺序才能使DataContractSerializer正常工作(不适用于XmlSerializer)
  • 此外,您必须在Skill和SkillCollection类之上包含名称和命名空间的[DataContract]属性,才能使其正常工作

1 个答案:

答案 0 :(得分:1)

你的两种方法都有一个基本但很容易修复的bug。

在方法1中,行:

new MemoryStream(Encoding.UTF8.GetBytes(Path.Combine(path, "Skills.xml")))

错误,因为内存流接收文件的 PATH 的字节表示, 而是它的实际内容。

在method2中,我猜它的错误相同,但是参数名称&#34; xml&#34;是误导。但是,由于您首先使用xml检查文件是否存在,我认为它还意味着文件的 PATH ,而不是其内容。

请改为尝试:

new MemoryStream(Encoding.UTF8.GetBytes(File.ReadAllText(Path.Combine(path, "Skills.xml"))))

假设DataContractSerializer的实际文件内容格式正确, 应该 工作。如果它没有,我会建议您首先序列化一个实时的SkillsCollection对象并查看它的外观,并以此为出发点。