csv to xml and lambda expressions

I have the following piece of code to convert a csv to an XML.

var xml = new XElement("root",
        lines.Where((line, index) => index > 0).Select(line => new XElement("TEST",
        line.Split(',').Select((column, index) => new XElement(headers[index], column)))))

I do get the big picture here. As in I get what each line does but I do not understand why some part like (line, index) is used. does this mean that when the index>0 then it sets the line to be that respective value?

I'd appreciate if someone can break this down for me. would be great if the lambda expressions are not used.

Jon Skeet
people
quotationmark

Firstly, it really helps if you indent more clearly:

var xml = new XElement("root",
    lines.Where((line, index) => index > 0) // Skips first line
         .Select(line => new XElement("TEST",
             line.Split(',')
                 .Select((column, index) => new XElement(headers[index], column)))))

In Visual Studio I would probably use more horizontal space, putting the line.Split on the same line as new XElement("TEST").

Now, any Where or Select call taking a lambda such as (value, index) received two pieces of information per item:

  • The value itself
  • The index within the sequence

So .Where((line, index) => index > 0 just means "ignore the first line". It would be more clearly written as .Skip(1).

Next, .Select((column, index) => new XElement(headers[index], column)) takes each column, and creates an element with the corresponding header as the element name, and column as the value. Personally, I'd write this using Zip, leaving:

var xml = new XElement("root",
    lines.Skip(1)
         .Select(line => new XElement("TEST",
             line.Split(',')
                 .Zip(headers, (value, header) => new XElement(header, value)))))

people

See more on this question at Stackoverflow