2

I'm begginer in linq to xml. i Have an xml file, i want to read it, and select object(bicycle) by Id. My test xml file is:

<Bikes>
<!--- - - - - - - - - - - - - - - - - - - -A new Bike- - - - - - - - - - - - - - - - - - - -->
    <Bike Id="1">
      <Big_Picture>Image</Big_Picture>
      <Small_Picture>Image</Small_Picture>
      <Emblem_Picture>Image</Emblem_Picture>
      <Firm>Image</Firm>
      <Model>Image</Model>
      <Price>Image</Price>
      <Colour>Image</Colour>
      <Frame_Size>Image</Frame_Size>
      <Description>Image</Description>
      <Gears>Image</Gears>
      <Groupset>Image</Groupset>
      <Brakes>Image</Brakes>
      <Frame_Material>Image</Frame_Material>
      <Wheel>Image</Wheel>
    </Bike>
</Bikes>

I want to select this bike by id (1), then put the elements of this bike in object of my class (Bike). How can i do that? My code, of course, doesn't perform the task:

XDocument xdoc = XDocument.Load("Bikes.xml");
xdoc.Descendants("Bike").Select(p => new {
        id = p.Attribute("Id").Value,
        picture = p.Element("Small_Picture").Value,
        model = p.Element("Model").Value,
        price = p.Element("Price").Value
    }).ToList().ForEach(p => {
        Bike bike = new Bike(p.id, p.picture, p.model, p.price);//Constructor
        bikes_xml.Add(bike);
    });
Gilad Green
  • 36,708
  • 7
  • 61
  • 95
Eldar
  • 47
  • 8

2 Answers2

1

If by doesn't work you mean you are getting all the items, all you need is a Where:

var bikes =  xdoc.Descendants("Bike")
                 .Where(e => (int)e.Attribute("Id") == 1)
                 .Select(p => new
                 {
                     id = p.Attribute("Id").Value,
                     picture = p.Element("Small_Picture").Value,
                     model = p.Element("Model").Value,
                     price = p.Element("Price").Value
                 }).ToList();

You can change your class to use properties if you aren't using them already, so you don't need to create an anonymous type. You can just use new Bike { ... }

Selman Genç
  • 100,147
  • 13
  • 119
  • 184
0

If you want to retrieve one bike as in your question then use FirstOrDefault:

var data = XDocument.Load("data.xml")
                    .Descendants("Bike")
                    .FirstOrDefault(item => item.Attribute("Id").Value == "1");
if(data != null)
{
    Bike bike = new Bike(data.Attribute("Id").Value,
                         data.Element("Small_Picture").Value,
                         data.Element("Model").Value,
                         data.Element("Price").Value);
}

If you want to construct it in the linq syntax then:

Bike x = (from bike in XDocument.Load("data").Descendants("Bike")
          select new Bike(bike.Attribute("Id").Value, 
                          bike.Element("Small_Picture").Value, 
                          bike.Element("Model").Value, 
                          bike.Element("Price").Value))
         .FirstOrDefault(item => item.Id == 1);    

And as @Selman Genç recommended, see if you can change to use Object Initializer instead of the constructor with the parameters. For more about it check What's the difference between an object initializer and a constructor?

Community
  • 1
  • 1
Gilad Green
  • 36,708
  • 7
  • 61
  • 95