【问题标题】:How to XML deserialize Dictionary, that hidden in other element?如何对隐藏在其他元素中的字典进行 XML 反序列化?
【发布时间】:2018-07-13 06:55:22
【问题描述】:

实际代码和 xml 文件

程序代码

class Program
{
    static void Main(string[] args)
    {
        string path = AppDomain.CurrentDomain.BaseDirectory + "file.xml";
        //string path2 = @"F:\fd.xml";
        FileStream fs = new FileStream(path, FileMode.Open);
XmlReader reader = XmlReader.Create(fs);
        SaveGame sav = new XmlSerializer(typeof(SaveGame)).Deserialize(reader) as SaveGame;
        Console.WriteLine(sav.player.friendshipData[0].key);
        Console.WriteLine(sav.player.friendshipData[0].value.Points);
        fs.Close();
        Console.ReadKey();
    }
}

public class SaveGame
{
    public Player player { get; set; }
}

public class Player
{
    public item[] friendshipData { get; set; }
}

public class item
{
    public string key { get; set; }
    public Friendship value { get; set; }
}

public class Friendship
{
    public int Points {get;set;}
}
}

要使用的 XML 文件:

<SaveGame>
    <player>
        <friendshipData>
            <item>
                <key>
                    <string>Name1</string>
                </key>
                <value>
                    <Friendship>
                        <Points>324</Points>
                    </Friendship>
                </value>
            </item>
            <item>
                <key>
                    <string>Name2</string>
                </key>
                <value>
                    <Friendship>
                        <Points>98</Points>
                    </Friendship>
                </value>
            </item>
        </friendshipData>
    </player>
</SaveGame>

我尝试了其他帖子,但这不起作用,因为所有读取的值都是空的。

请问,如何反序列化这个文件?请解释一下。

如果我将 {get;set;} 设置为变量,它不会读取下一个项目,如果我设置 {get;} 它会读取每个项目,但每个项目都有空值。

以防万一,由于某些原因,我无法编辑 XML 文件。 XML 文件没问题。

【问题讨论】:

  • “因为我一直得到一个异常,这意味着我不能反序列化这个 XML 文档。”请具体说明您尝试过的excatly 以及遇到的异常情况。我怀疑您是否希望我们发布您已经尝试过的相同方法,是吗?所以请帮助我们写出真正对您有帮助的有意义的答案。
  • 除非我们知道您的数据结构,否则这并没有多大帮助。请显示您的代码、类型和反序列化方式。再说一遍:发布异常
  • 等一下……
  • 写你想要的

标签: c# xml serialization deserialization


【解决方案1】:

您的数据结构并不适合您的 xml。如果您有一个简单的数据类型,例如intstring,您可以将直接序列化和反序列化到一个 xml 节点中。如果您有一些更复杂的数据结构,例如 Firnedship-node,您需要一个嵌套节点。

话虽如此,您的数据结构应该类似于以下内容:

public class SaveGame
{
    public Player player { get; set; }
}

public class Player
{
    public item[] friendshipData { get; set; }
}

public class item
{
    public Key key { get; set; }
    public Friendship value { get; set; }
}

// add this class with a single string-field
public class Key
{
    public string @string { get; set;  }
}

public class Friendship
{
    public int Points { get; set; }
}

顺便考虑一下命名约定,它为类和这些类的成员提供 PascaleCase 名称,例如FriendshipDataItemKey。然而,这假设您有一些从这些名称到 xml 中的名称的映射。这可以通过使用XmlElementAttribute来完成:

public class Player
{
    [XmlElement("friendshipData ")] // see here how to change the name within the xml
    public item[] FriendshipData { get; set; }
}

【讨论】:

    【解决方案2】:

    由于您只需要来自 Xml 的两个值,因此我不会使用序列化。你可以得到一本带有一条 linq 指令的字典。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Xml;
    using System.Xml.Linq;
    
    namespace ConsoleApplication51
    {
    
        class Program
        {
            const string FILENAME = @"c:\temp\test.xml";
    
            static void Main(string[] args)
            {
                XDocument doc = XDocument.Load(FILENAME);
    
                Dictionary<string, int> players = doc.Descendants("item")
                    .GroupBy(x => (string)x.Descendants("string").FirstOrDefault(), y => (int)y.Descendants("Points").FirstOrDefault())
                    .ToDictionary(x => x.Key, y => y.FirstOrDefault());
    
            }
        }
    
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-04-08
      • 1970-01-01
      • 2011-12-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-24
      • 1970-01-01
      相关资源
      最近更新 更多