Search code examples
c#linqlinq-to-xmlxelement

Linq to XElement, multiple parameters


I am creating an XElement object and have problems adding multiple elements to a node using Linq.

There's a list of objects with multiple properties:

class Point { int x; int y; ... }

List<Point> Points = new List<Point>()
{ 
  new Point(1,2), 
  new Point(3,4) 
};

I would like to convert this list to a flat XElement using single constructor (in one go).

What I want to see:

<Points>
  <x>1</x>
  <y>2</y>
  <x>3</x>
  <y>4</y>
</Points>

The furthest I got so far:

new XElement("Points",
  Points.Select(a => new {
    X = new XElement("x", a.x),
    Y = new XElement("y", a.y)
  });

Which produces a nested list, parsed as a single XElement.

<Points>{ X = <x>1</x>, Y = <y>2</y> }{ X = <x>3</x>, Y = <y>4</y> }</Points>

(I need to preserve the order so union wouldn't work)

I want to do everything in the constructor, like above, and don't want to manually add points like so:

XElement PointsXml = new XElement("Points");
foreach (var item in Points)
{
  PointsXml.Add(item.x);
  PointsXml.Add(item.y);
}

Solution

  • The following would work:

    var xml= new XElement("Points", 
        Points.SelectMany(a => new [] { new XElement("x", a.x), new XElement("y", a.y)}));
    

    Or if you'd like to wrap each point in its own element then:

    var xml= new XElement("Points", 
        Points.Select(a => 
            new XElement("Point", new XElement("x", a.x), new XElement("y", a.y))));
    

    The trick is to always add objects of XElement. The code you used will retrun an anonymous object and not this XElement array that is needed