Convert a CSV to XML using C#

I wrote a simple class that will help you convert a CSV file to XML. I can hear you asking “that’s nice JP, but why would I want to convert my simple CSV to that messy text format from the early 2000’s?” You would do this because you want to use LINQ with CSV files… that’s why.

Here is the crux of the algorithm:

public void Convert() {
	var tempLines = File.ReadAllLines(this.CsvFile);
	string[] lines = null;
	_columnNames = null;
	
	if (this.HasColumnNames) {
		_columnNames = Csv.RecordSplit(tempLines[0], this.RecordDelimiter, this.TextQualifier);
	
		lines = new string[tempLines.Length - 1];
		Array.Copy(tempLines, 1, lines, 0, lines.Length);
	} else {
		var columnCount = Csv.RecordSplit(tempLines[0], this.RecordDelimiter, this.TextQualifier).Length;
		_columnNames = new string[columnCount];
		for (int x = 0; x < _columnNames.Length; ++x)
			_columnNames[x] = "Column" + (x+1);
	
		lines = tempLines;
	}
	
	this.XmlData = new XElement("Records",
		from line in lines
		let fields = Csv.RecordSplit(line, this.RecordDelimiter, this.TextQualifier)
		select new XElement("Record",
			from fieldData in fields
			let i = fields.ToList().FindIndex(f => f == fieldData)
			select new XElement(_columnNames[i], fieldData)
		)
	);
}

You can look at the full code in my C# CommonLib library. As you can see, the code is really straightforward.

Let’s assume that your CSV file looks like this:

'Product','Price','DateStocked'
'Pepsi','4.50','2010-05-04'
'Coke','3.00','2010-09-22'
'Cheetos','7.25','2009-01-13'

You can then run Csv2Xml like this:

var csv = new CsvToXml(csvFile);
csv.RecordDelimiter = ','; 
csv.TextQualifier = '\'';
csv.HasColumnNames = false;
csv.Convert();

var actualXml = csv.XmlString;

The output XML will look like this:

<?xml version="1.0" encoding="utf-8"?>
<Records>
	<Record>
		<Column1>Pepsi</Column1>
		<Column2>4.50</Column2>
		<Column3>2010-05-04</Column3>
	</Record>
	<Record>
		<Column1>Coke</Column1>
		<Column2>3.00</Column2>
		<Column3>2010-09-22</Column3>
	</Record>
	<Record>
		<Column1>Cheetos</Column1>
		<Column2>7.25</Column2>
		<Column3>2009-01-13</Column3>
	</Record>
</Records>

If you set “HasColumnNames” to “True”, your XML output will look like this:

<?xml version="1.0" encoding="utf-8"?>
<Records>
	<Record>
		<Product>Pepsi</Product>
		<Price>4.50</Price>
		<DateStocked>2010-05-04</DateStocked>
	</Record>
	<Record>
		<Product>Coke</Product>
		<Price>3.00</Price>
		<DateStocked>2010-09-22</DateStocked>
	</Record>
	<Record>
		<Product>Cheetos</Product>
		<Price>7.25</Price>
		<DateStocked>2009-01-13</DateStocked>
	</Record>
</Records>

Are you a Git user? Let me help you make project management with Git simple. Checkout Gitpilot.

Pretty nifty huh? In the next post, I’ll explain how you can use this with LINQ. In the mean time follow me on Twitter (@jprichardson) or read my blog on entrepreneurship: Techneur.

-JP

About JP
Exodus Co-Founder (www.exodus.io)

12 Responses to Convert a CSV to XML using C#

  1. aussiecraig says:

    JP,
    You have an interesting approach to this sort of problem.
    I must admit my approach is usually is to suck the CSV up into a collection of objects and use LINQ to Objects on the resulting List.
    I’ve always found LINQ to XML harder to work with than LINQ to objects.
    Craig

    • JP says:

      Craig,

      I appreciate you leaving a comment. I think you’ll find that after you read my next post, you’ll think that this approach is pretty straightforward. At least I would be interested in your thoughts. It takes advantage of DynamicObject and allows you to not have define an object every time.

      -JP

      • aussiecraig says:

        JP,

        I must agree with you, translating the CSV to XML gives a simulation of dynamic objects. Hence, this approach does have some benefits that a LINQ to Objects approach would not have.

        You remind me of an article on MSDN (if recollection serves correct, I’ll go and dig up the URL – found it!). Expando Objects in C# 4.0 .

        I skimmed the article a while back, and filed it away as something to get back to. I’ll have a real read of it next, could be a post on my blog coming up, about using Expando Objects, CSV files, and LINQ.

        Craig

      • JP says:

        That’s similar to what I did. Here is the new post showing how to use my CsvToXml class with LINQ:

        http://procbits.com/2010/10/11/using-linq-with-csv-files/

  2. Pingback: Using LINQ with CSV Files « Procbits

  3. Pingback: CSV, ExpandoObject and LINQ « Craig's Eclectic Blog

  4. joeri says:

    Hello JP,

    great stuff you have here.

    i have a bit of a issue. 🙂
    hope you can help me resolve it.

    the csv provided to me, looks like this
    Product;Price;DateStocked;
    Pepsi;4.50;2010-05-04;
    Coke;3.00;2010-09-22;
    Cheetos;7.25;2009-01-13;

    so basically there is no textdelimiter, but i can get arround that by setting it to null,
    however, the csv i get, also has a ; character at the end of each line. and the convert to xml does seem to trip over it.

    any clue on how i can get that resolved ?

    thank you in advance.

    Regards
    Joeri

  5. jc says:

    hi..i tried out your code but im missing a reference for the CommonLib..what reference should i add?thanks

Leave a comment