我有一个字典,其中键是路径,值是字符串
root/A/A1/A1A value
root/A/A1/A1B value
root/A/A1/A1C value
root/A/A2/A2A value
root/A/A2/A2B value
root/B/B1/B1A value
从接收字典的方法中,我想生成如下所示的XML文件:
<root>
<A>
<A1>
<A1A>value</A1A>
<A1B>value</A1B>
<A1C>value</A1C>
</A1>
<A2>
<A2A>value</A2A>
<A2B>value</A2B>
</A2>
</A>
<B>
<B1>
<B1A>value</B1A>
</B1>
</B>
</root>
您可以使用 Linq 分组来解决此问题
带循环:
static void WithLinqLoop(Dictionary<string, string> dict)
{
var flats = from kvp in dict
let arr = kvp.Key.Split('/')
select new { l0 = arr[0], l1 = arr[1], l2 = arr[2], l3 = arr[3], l4 = kvp.Value };
var q = from f in flats
group f by f.l0 into g0
select new
{
el = g0.Key,
g = from f in g0
group f by f.l1 into g1
select new
{
el = g1.Key,
g = from f in g1
group f by f.l2 into g2
select new
{
el = g2.Key,
g = from f in g2
group f by f.l3 into g3
select new
{
el = g3.Key,
val = g3.First().l4
}
}
}
};
using (var sw = new StringWriter())
{
using (var xw = new System.Xml.XmlTextWriter(sw) { Formatting = System.Xml.Formatting.Indented })
{
foreach (var n in q)
{
xw.WriteStartElement(n.el);
foreach (var n1 in n.g)
{
xw.WriteStartElement(n1.el);
foreach (var n2 in n1.g)
{
xw.WriteStartElement(n2.el);
foreach (var n3 in n2.g)
{
xw.WriteStartElement(n3.el);
xw.WriteString(n3.val);
xw.WriteEndElement();
}
xw.WriteEndElement();
}
xw.WriteEndElement();
}
xw.WriteEndElement();
}
}
var xml = sw.ToString();
Console.WriteLine(xml);
}
}
使用递归:
static void WithLinqRec(Dictionary<string, string> dict)
{
var flats = from kvp in dict
let arr = kvp.Key.Split('/')
select new { l0 = arr[0], l1 = arr[1], l2 = arr[2], l3 = arr[3], l4 = kvp.Value };
var q = from f in flats
group f by f.l0 into g0
select new
{
el = g0.Key,
g = from f in g0
group f by f.l1 into g1
select new
{
el = g1.Key,
g = from f in g1
group f by f.l2 into g2
select new
{
el = g2.Key,
g = from f in g2
group f by f.l3 into g3
select new
{
el = g3.Key,
g = g3.First().l4
}
}
}
};
var sw = new StringWriter();
var xw = new System.Xml.XmlTextWriter(sw) { Formatting = System.Xml.Formatting.Indented };
Action<dynamic> writeNode = null;
writeNode = (n) =>
{
xw.WriteStartElement(n.el);
if (typeof(string) == n.g.GetType())
{
xw.WriteString(n.g);
}
else
{
foreach (var n1 in n.g)
writeNode(n1);
}
xw.WriteEndElement();
};
foreach (var n in q)
writeNode(n);
var xml = sw.ToString();
Console.WriteLine(xml);
}
或使用 GroupByMany 扩展 (https://blogs.msdn.microsoft.com/mitsu/2007/12/21/playing-with-linq-grouping-groupbymany/(
static void WithGroupByManyRec(Dictionary<string, string> dict)
{
var flats = from kvp in dict
let arr = kvp.Key.Split('/')
select new { l0 = arr[0], l1 = arr[1], l2 = arr[2], l3 = arr[3], l4 = kvp.Value };
var grouped = flats.GroupByMany(f => f.l0, f => f.l1, f => f.l2, f => f.l3);
var sw = new StringWriter();
var xw = new System.Xml.XmlTextWriter(sw) { Formatting = System.Xml.Formatting.Indented };
Action<GroupResult> writeNode = null;
writeNode = (res) =>
{
xw.WriteStartElement(res.Key.ToString());
if (res.SubGroups == null)
{
foreach (dynamic v in res.Items)
{
xw.WriteString(v.l4.ToString());
}
}
else
{
foreach (var n1 in res.SubGroups)
writeNode(n1);
}
xw.WriteEndElement();
};
foreach (var n in grouped)
writeNode(n);
var xml = sw.ToString();
Console.WriteLine(xml);
}