我需要将CSV转换为XML文档。我到目前为止看到的示例都显示了如何使用CSV中的固定数量的列进行此操作。
到目前为止,我使用LINQ:
String[] File = File.ReadAllLines(@"C:\text.csv");
String xml = "";
XElement top = new XElement("TopElement",
from items in File
let fields = items.Split(';')
select new XElement("Item",
new XElement("Column1", fields[0]),
new XElement("Column2", fields[1]),
new XElement("Column3", fields[2]),
new XElement("Column4", fields[3]),
new XElement("Column5", fields[4])
)
);
File.WriteAllText(@"C:\xmlout.xml", xml + top.ToString());
这是针对固定数量的列,但我的.CSV在每一行上都有不同的列数。
根据.CSV每行中有多少单词(列),你会如何适应某种循环?
日Thnx
答案 0 :(得分:27)
var lines = File.ReadAllLines(@"C:\text.csv");
var xml = new XElement("TopElement",
lines.Select(line => new XElement("Item",
line.Split(';')
.Select((column, index) => new XElement("Column" + index, column)))));
xml.Save(@"C:\xmlout.xml");
输入:
A;B;C
D;E;F
G;H
输出:
<TopElement>
<Item>
<Column0>A</Column0>
<Column1>B</Column1>
<Column2>C</Column2>
</Item>
<Item>
<Column0>D</Column0>
<Column1>E</Column1>
<Column2>F</Column2>
</Item>
<Item>
<Column0>G</Column0>
<Column1>H</Column1>
</Item>
</TopElement>
答案 1 :(得分:9)
如果您想使用标题作为元素名称:
var lines = File.ReadAllLines(@"C:\text.csv");
string[] headers = lines[0].Split(',').Select(x => x.Trim('\"')).ToArray();
var xml = new XElement("TopElement",
lines.Where((line, index) => index > 0).Select(line => new XElement("Item",
line.Split(',').Select((column, index) => new XElement(headers[index], column)))));
xml.Save(@"C:\xmlout.xml");
答案 2 :(得分:3)
我写了一个源自Vlax代码片段的课程。 另外,我提供了一个单元测试来记录工作流程。
单元测试:
[TestMethod]
public void convert_csv_to_xml()
{
// Setup
var csvPath = @"Testware\vendor.csv";
var xmlPath = @"Testware\vendor.xml";
// Test
var success = DocumentConverter.Instance.CsvToXml(csvPath, xmlPath);
// Verify
var expected = File.Exists(xmlPath) && success;
Assert.AreEqual(true, expected);
}
CSV到XML:
public class DocumentConverter
{
#region Singleton
static DocumentConverter _documentConverter = null;
private DocumentConverter() { }
public static DocumentConverter Instance
{
get
{
if (_documentConverter == null)
{
_documentConverter = new DocumentConverter();
}
return _documentConverter;
}
}
#endregion
public bool CsvToXml(string sourcePath, string destinationPath)
{
var success = false;
var fileExists = File.Exists(sourcePath);
if (!fileExists)
{
return success;
}
var formatedLines = LoadCsv(sourcePath);
var headers = formatedLines[0].Split(',').Select(x => x.Trim('\"').Replace(" ", string.Empty)).ToArray();
var xml = new XElement("VendorParts",
formatedLines.Where((line, index) => index > 0).
Select(line => new XElement("Part",
line.Split(',').Select((field, index) => new XElement(headers[index], field)))));
try
{
xml.Save(destinationPath);
success = true;
}
catch (Exception ex)
{
success = false;
var baseException = ex.GetBaseException();
Debug.Write(baseException.Message);
}
return success;
}
private List<string> LoadCsv(string sourcePath)
{
var lines = File.ReadAllLines(sourcePath).ToList();
var formatedLines = new List<string>();
foreach (var line in lines)
{
var formatedLine = line.TrimEnd(',');
formatedLines.Add(formatedLine);
}
return formatedLines;
}
}
注意:
我通过删除导致运行时异常的每个CSV行条目的尾随逗号来扩展Vlax的解决方案,因为索引超出了与列标题相关的范围。
答案 3 :(得分:0)
Cinchoo ETL-一个开放源代码库,可使用几行代码轻松地将CSV转换为Xml
对于示例CSV:
string csv = @"Id, Name, City
1, Tom, NY
2, Mark, NJ
3, Lou, FL
4, Smith, PA
5, Raj, DC
";
StringBuilder sb = new StringBuilder();
using (var p = ChoCSVReader.LoadText(csv)
.WithFirstLineHeader()
)
{
using (var w = new ChoXmlWriter(sb)
.Configure(c => c.RootName = "Employees")
.Configure(c => c.NodeName = "Employee")
)
w.Write(p);
}
Console.WriteLine(sb.ToString());
输出Xml:
<Employees>
<Employee>
<Id>1</Id>
<Name>Tom</Name>
<City>NY</City>
</Employee>
<Employee>
<Id>2</Id>
<Name>Mark</Name>
<City>NJ</City>
</Employee>
<Employee>
<Id>3</Id>
<Name>Lou</Name>
<City>FL</City>
</Employee>
<Employee>
<Id>4</Id>
<Name>Smith</Name>
<City>PA</City>
</Employee>
<Employee>
<Id>5</Id>
<Name>Raj</Name>
<City>DC</City>
</Employee>
</Employees>
查看CodeProject文章以获取其他帮助。
免责声明:我是这个图书馆的作者。
答案 4 :(得分:0)
此处提供了不使用嵌套LINQ的解决方案,更易于理解。
input.csv
的内容:
A,B,C
D,E,F
G,H
流程代码:
Program.cs
using System;
using System.IO;
using System.Linq;
using System.Xml.Linq;
namespace CSVtoXML
{
class Program
{
private static void AddContentForEachLine(string line, ref XElement xmlTree)
{
var currentTree = new XElement("Item");
const string delimiter = ","; // Can be changed based on the actual situation
string[] slices = line.Split(delimiter);
for (int i = 0; i < slices.Count(); i++)
currentTree.Add(new XElement($"Column{i}", slices[i].ToString()));
xmlTree.Add(currentTree);
}
static void Main(string[] args)
{
var basePath = Environment.CurrentDirectory;
var lines = File.ReadAllLines(Path.Combine(basePath, "../../..", @"input.csv"));
var xmlTree = new XElement("TopElement");
foreach (var line in lines)
{
AddContentForEachLine(line, ref xmlTree);
}
xmlTree.Save(Path.Combine(basePath, "../../..", @"output.xml"));
}
}
}
运行代码后,结果如下:
<?xml version="1.0" encoding="utf-8"?>
<TopElement>
<Item>
<Column0>A</Column0>
<Column1>B</Column1>
<Column2>C</Column2>
</Item>
<Item>
<Column0>D</Column0>
<Column1>E</Column1>
<Column2>F</Column2>
</Item>
<Item>
<Column0>G</Column0>
<Column1>H</Column1>
</Item>
</TopElement>
可以在此处查看此代码的完整Visual Studio解决方案:
https://github.com/yanglr/dotnetInterview/tree/master/CSVtoXML。