我有这个让我夜不能寐的问题。这是很长的解释,所以提前感谢你专注于这个主题的时间。
我想在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和两个词典快速创建类似的东西:
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列表,因为我不知道每个节点中有多少子节点。这使我无法访问多个子节点,就像我在第一部分中所示,因为Object不是List。
有没有办法真正解决这个问题? 我有一种方法可以根据我的需要将对象列表转换为Dictionary列表,但我真的不知道它是如何工作的。
答案 0 :(得分:0)
为了避免嵌套泛型类型,您可以使用索引器创建一些非泛型类包装器,并在其中移动字典或列表的定义:
public class DictionaryNode
{
public Dictionary<string, ListNode> Dictionary { get; } = new Dictionary<string, ListNode>();
public ListNode this[string name]
{
get
{
return Dictionary[name];
}
}
}
public class ListNode
{
public List<DictionaryNode> List { get; } = new List<DictionaryNode>();
public DictionaryNode this[int index]
{
get
{
return List[index];
}
}
//to make writing [0] optional
public ListNode this[string name]
{
get
{
return List[0][name];
}
}
}
使用这样的包装器,您可以创建这样的树结构:
var node1 = new DictionaryNode();
var node2 = new ListNode();
var node3 = new DictionaryNode();
var node4 = new ListNode();
node4.List.AddRange(new[] { new DictionaryNode(), new DictionaryNode() });
node3.Dictionary.Add("bb", node4);
node2.List.Add(node3);
node1.Dictionary.Add("aa", node2);
var n = node1["aa"][0]["bb"][1];
var n2 = node1["aa"]["bb"][1];
答案 1 :(得分:0)
我使用了以下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());
}
}
}