Convert CSV file to XML
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");
Input:
A;B;C
D;E;F
G;H
Output:
<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>
In case you want use the headers as the elements names:
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");
I wrote a class that derives from Vlax's snippet. In addition I have provided a unit test to document the workflow.
Unit Test:
[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 to 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;
}
}
NOTE:
I extended Vlax's solution by removing a trailing comma for each of the CSV line entries that caused a runtime exception based on an index being out of bounds in relation to the column header.