从 CSV 生成 XML 时对 XElement 进行分组
Grouping XElement when generating XML from CSV
假设我有一个由第 3 方生成且无法更改的 *.csv。
ProjectName
Fruit, Apple
Fruit, Orange
Animal, Dog
Animal, Cat
使用Generate XML from CSV Files中的教程,只好删除第一行,得到如下:
<Fruit>
<Apple></Apple>
</Fruit>
<Fruit>
<Orange></Orange>
</Fruit>
<Animal>
<Dog></Dog>
</Animal>
<Animal>
<Cat></Cat>
</Animal>
虽然我想实现以下目标,但找不到任何资源或教程来了解如何做到这一点:
<Project Name="ProjectName">
<Fruit>
<Apple></Apple>
<Orange></Orange>
</Fruit>
<Animal>
<Dog></Dog>
<Cat></Cat>
</Animal>
</Project>
假设文件的第一行始终是名称,请先读出该行,然后将其余部分处理为 CSV。读取行后,将它们按适当的列分组并构建 XML.
XDocument GetXml(string path)
{
using (var file = File.OpenText(path))
{
var name = file.ReadLine();
return new XDocument(
new XElement("Project",
new XAttribute("Name", name),
from row in ReadRows(file)
group row.Item2 by row.Item1 into g
select new XElement(g.Key,
from r in g
select new XElement(r)
)
)
);
}
}
IEnumerable<Tuple<string, string>> ReadRows(TextReader file)
{
using (var reader = new CsvReader(file, new CsvConfiguration { HasHeaderRecord = false, TrimFields = true }))
{
while (reader.Read())
yield return Tuple.Create(reader.GetField(0), reader.GetField(1));
}
}
假设我有一个由第 3 方生成且无法更改的 *.csv。
ProjectName
Fruit, Apple
Fruit, Orange
Animal, Dog
Animal, Cat
使用Generate XML from CSV Files中的教程,只好删除第一行,得到如下:
<Fruit>
<Apple></Apple>
</Fruit>
<Fruit>
<Orange></Orange>
</Fruit>
<Animal>
<Dog></Dog>
</Animal>
<Animal>
<Cat></Cat>
</Animal>
虽然我想实现以下目标,但找不到任何资源或教程来了解如何做到这一点:
<Project Name="ProjectName">
<Fruit>
<Apple></Apple>
<Orange></Orange>
</Fruit>
<Animal>
<Dog></Dog>
<Cat></Cat>
</Animal>
</Project>
假设文件的第一行始终是名称,请先读出该行,然后将其余部分处理为 CSV。读取行后,将它们按适当的列分组并构建 XML.
XDocument GetXml(string path)
{
using (var file = File.OpenText(path))
{
var name = file.ReadLine();
return new XDocument(
new XElement("Project",
new XAttribute("Name", name),
from row in ReadRows(file)
group row.Item2 by row.Item1 into g
select new XElement(g.Key,
from r in g
select new XElement(r)
)
)
);
}
}
IEnumerable<Tuple<string, string>> ReadRows(TextReader file)
{
using (var reader = new CsvReader(file, new CsvConfiguration { HasHeaderRecord = false, TrimFields = true }))
{
while (reader.Read())
yield return Tuple.Create(reader.GetField(0), reader.GetField(1));
}
}