我有点卡住,不能直接思考,也许你能帮助我。
我的.xml看起来像这样:
<RSA>
<Size>
<Name>0005-24</Name>
<IDs>
<ID>0003</ID>
<ID>0004</ID>
<ID>0005</ID>
<ID>0006</ID>
<ID>0007</ID>
<ID>0008</ID>
<ID>0010</ID>
<ID>0009</ID>
</IDs>
</Size>
<Size>
<Name>0015-24</Name>
<IDs>
<ID>0003</ID>
<ID>0004</ID>
<ID>0005</ID>
<ID>0006</ID>
<ID>0007</ID>
<ID>0008</ID>
<ID>0010</ID>
<ID>0009</ID>
</IDs>
</Size>
<Size>
<Name>003-12</Name>
<IDs>
<ID>0003</ID>
<ID>0004</ID>
<ID>0005</ID>
<ID>0006</ID>
<ID>0007</ID>
<ID>0008</ID>
<ID>0010</ID>
<ID>0009</ID>
</IDs>
</Size>
</RSA>
ID应该是为了便于阅读。
修改
<Size>
<Name>0005-24</Name>
<IDs>
<ID>0003</ID>
<ID>0004</ID>
<ID>0005</ID>
<ID>0006</ID>
<ID>0007</ID>
<ID>0008</ID>
<ID>0010</ID> <-----
<ID>0009</ID> <-----
</IDs>
</Size>
所以这些应该是有序的。
[...]
<ID>0009</ID> <-----
<ID>0010</ID> <-----
[...]
我尝试了很多不同的方法,但我的最后一个方法以下面的代码结束,这也不起作用。
XElement root = XElement.Load(filePath + fileName);
var compIDs = root.Elements()
.GroupBy(r => r.Element("Name").Value)
.OrderBy(xn => xn.Elements("RSA").Elements("Size").Elements("IDs").Elements("ID").ToString())
.ToArray();
root.ReplaceAll(compIDs);
root.Save(filePath + fileName);
我提前搜索了SO,但找不到任何有用的东西,或者只是我不懂的东西。 ;)
问题:如何按照大小对条目进行分组,按顺序显示ID并将其替换为xml文件?
提前致谢!
答案 0 :(得分:2)
您可以这样做:
var filename = ...
XDocument root = XDocument.Load(filename);
foreach (var ids_element in root.Descendants("IDs"))
{
ids_element.ReplaceNodes(ids_element.Elements().OrderBy(x => x.Value));
}
root.Save(filename);
此代码会更改XDocument
。它循环遍历name&#34; IDs&#34;的所有元素,并用这些子元素的排序版本替换子元素。
答案 1 :(得分:0)
也许这会有所帮助:
class Program
{
static void Main(string[] args)
{
var root = XElement.Load("1.xml");
var compIDs = root.Elements()
.GroupBy(r => r.Element("Name").Value)
.Select(group => new
{
Group = group.Key,
Items = group.First().Elements("IDs").Elements("ID")
.Select(id => new Regex("<ID>(.*)</ID>").Match(id.ToString()).Groups[1].ToString())
.OrderBy(value => value)
.ToArray()
}
)
.ToArray();
using (var sw = new StreamWriter("results.txt"))
{
foreach (var group in compIDs)
{
sw.WriteLine("Size: " + group.Group + "\r\nIDs:");
foreach (var id in group.Items)
sw.WriteLine(id);
}
}
}
}
产出结果:
Size: 0005-24
IDs:
0003
0004
0005
0006
0007
0008
0009
0010
Size: 0015-24
IDs:
0003
0004
0005
0006
0007
0008
0009
0010
Size: 003-12
IDs:
0003
0004
0005
0006
0007
0008
0009
0010
答案 2 :(得分:0)
编辑:这是在修改问题之前编写的,以包含XML输出。假设OP想要将数据转换为聚合的CLR对象。
我昨天在求职面试中遇到了这个问题,我也很努力,所以当我回到家时,我做了一些自己的测试,以确保它只是压力,而我的大脑并没有完全炒:)
您需要对数据进行分组,然后将其投影到新表单中,以便能够按新元素进行排序。然后,您需要告诉GroupBy您希望如何聚合它。
您可以投影到匿名类型或可以单独定义的新类。在这里,我只是使用匿名类型。
这是一个工作的控制台应用程序。我添加了一些测试数据来正确测试分组和聚合。我建议在您的生产应用程序中进行一些额外的空检查:
using System;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1 {
internal class Program {
private static void Main(string[] args) {
var xml = @"<RSA>
<Size>
<Name>0005-24</Name>
<IDs>
<ID>0005</ID>
<ID>0009</ID>
</IDs>
</Size>
<Size>
<Name>0005-24</Name>
<IDs>
<ID>0003</ID>
<ID>0004</ID>
<ID>0005</ID>
<ID>0006</ID>
<ID>0007</ID>
<ID>0008</ID>
<ID>0010</ID>
<ID>0009</ID>
</IDs>
</Size>
<Size>
<Name>0015-24</Name>
<IDs>
<ID>0003</ID>
<ID>0004</ID>
<ID>0005</ID>
<ID>0006</ID>
<ID>0007</ID>
<ID>0008</ID>
<ID>0010</ID>
<ID>0009</ID>
<ID>0034</ID>
<ID>0078</ID>
</IDs>
</Size>
<Size>
<Name>003-12</Name>
<IDs>
<ID>0003</ID>
<ID>0004</ID>
<ID>0005</ID>
<ID>0006</ID>
<ID>0007</ID>
<ID>0008</ID>
<ID>0010</ID>
<ID>0009</ID>
</IDs>
</Size>
</RSA>";
var stream = new MemoryStream(Encoding.UTF8.GetBytes(xml));
var reader = new XmlTextReader(stream);
var root = XElement.Load(reader);
var names = root.Elements("Size") // Get each top level size element to make the query more efficient
.GroupBy(r => r.Element("Name").Value, // Group by the name element
(key, Ids) => new {
Name = key,
Ids = Ids.SelectMany(x => x.Element("IDs").Elements("ID").Select(e => e.Value)).Distinct()
}) // project to new form and evaluate the group
.OrderBy(x => x.Name); // Order by the top level grouping
foreach(var name in names) {
Console.Write((string.Concat("Name: ", name.Name, " - ")));
foreach(var id in name.Ids.OrderBy(x => int.Parse(x))) {
// Order by the integer representation (needs additional checking with TryParse())
Console.Write(string.Concat(id, ", "));
}
Console.WriteLine();
}
Console.ReadLine();
}
}
}