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;CD;E;FG;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.