c# - 用索引初始化和访问字典中不知道数量的列表
问题描述
我有这个问题让我彻夜难眠。解释起来很长,所以提前感谢您为这个主题付出的时间。
上下文
我想在 C# 中创建一个类来获取 XML 文件的全部内容,其中节点名称作为索引,并使用列表和字典的组合以树的方式排序。
目标是能够使用如下名称和索引访问特定数据:
Console.WriteLine(xmlContent["employee"][0]["e-mail"][1]);
//Would return the second email from the first employee register in the xml file.
我几乎可以肯定这是可能的。我使用一个列表和两个字典快速创建了类似的东西:
List<Dictionary<string, Dictionary<string, string>>> test = new List<Dictionary<string, Dictionary<string, string>>>();
Dictionary<string, Dictionary<string, string>> column1 = new Dictionary<string, Dictionary<string, string>>();
Dictionary<string, Dictionary<string, string>> column2 = new Dictionary<string, Dictionary<string, string>>();
Dictionary<string, string> C1ligne1 = new Dictionary<string, string>();
C1ligne1.Add("value1", "C1ligne1 1");
C1ligne1.Add("value2", "C1ligne1 2");
Dictionary<string, string> C1ligne2 = new Dictionary<string, string>();
C1ligne2.Add("value1", "C1ligne2 1");
C1ligne2.Add("value2", "C1ligne2 2");
Dictionary<string, string> C2ligne1 = new Dictionary<string, string>();
C2ligne1.Add("value1", "C2ligne1 1");
C2ligne1.Add("value2", "C2ligne1 2");
Dictionary<string, string> C2ligne2 = new Dictionary<string, string>();
C2ligne2.Add("value1", "C2ligne2 1");
C2ligne2.Add("value2", "C2ligne2 2");
column1.Add("line1", C1ligne1);
column1.Add("line2", C1ligne2);
column2.Add("line1", C2ligne1);
column2.Add("line2", C2ligne2);
test.Add(column1);
test.Add(column2);
Console.WriteLine(test[0]["line1"]["value1"]); //"C1ligne1 1"
Console.WriteLine(test[0]["line2"]["value2"]); //"C1ligne2 2"
Console.WriteLine(test[1]["line1"]["value2"]); //"C2ligne1 2"
它真的很好用!
问题
我设法使用方法和函数制作了我想要的东西,它就像我想要的那样工作:
public void getContent(ref Dictionary<string, List<Object>> content)
{
foreach (XmlNode node in xmlDoc.DocumentElement.ChildNodes)
{
if (!content.ContainsKey(node.Name))
{
content.Add(node.Name, new List<Object>());
content[node.Name].Add(this.nodeContent(node));
}
else
{
content[node.Name].Add(this.nodeContent(node));
}
}
}
private Dictionary<string, List<Object>> nodeContent(XmlNode specificNode)
{
Dictionary<string, List<Object>> content = new Dictionary<string, List<Object>>();
foreach (XmlNode nodeInSpecificNode in specificNode.ChildNodes)
{
if (nodeInSpecificNode.ChildNodes.Count > 1)
{
content.Add(nodeInSpecificNode.Name, new List<object> ());
content[nodeInSpecificNode.Name].Add(this.nodeContent(nodeInSpecificNode));
}
else
{
content.Add(nodeInSpecificNode.Name, new List<Object>());
content[nodeInSpecificNode.Name].Add(nodeInSpecificNode.InnerText);
}
}
return content;
}
不幸的是,它迫使我使用对象列表,因为我不知道每个节点中有多少子节点。这使我无法像我在第一部分中展示的那样访问多个子节点,因为 Object 不是 List。
问题
有没有办法真正解决这个问题?我虽然有一种方法可以根据我的需要将对象列表转换为字典列表,但我真的不知道它是如何工作的。
解决方案
我使用了以下 xml:
<?xml version="1.0" encoding="utf-8" ?>
<test>
<line1>
<value1>C1ligne1 1</value1>
<value2>C1ligne1 2</value2>
</line1>
<line2>
<value1>C1ligne2 1</value1>
<value2>C1ligne2 2</value2>
</line2>
<line1>
<value1>C2ligne1 1</value1>
<value2>C2ligne1 2</value2>
</line1>
<line2>
<value1>C2ligne2 1</value1>
<value2>C2ligne2 2</value2>
</line2>
</test>
这是创建两级字典的代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = @"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
Dictionary<string, Dictionary<string,string>> dict = doc.Element("test").Elements()
.GroupBy(x => x.Name.LocalName, y => y.Elements()
.GroupBy(a => a.Name.LocalName, b => (string)b)
.ToDictionary(a => a.Key, b => b.FirstOrDefault()))
.ToDictionary(x => x.Key, y => y.FirstOrDefault());
}
}
}