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.

Tags:

C#

Xml

Csv