lior
lior

Reputation: 61

Use the object returned by LINQ

I'm using LINQ to find an object from an XML file. After I find the object, I want to print its details, but I'm not really sure how I can use the object I found.

This is my code:

var apartmentExist =
    from apartment1 in apartmentXml.Descendants("Apartment")
    where (apartment1.Attribute("street_name").Value == newApartment.StreetName) &&
          (apartment1.Element("Huose_Num").Value == newApartment.HouseNum.ToString())
    select apartment1.Value;
if (apartmentExist.Any() == false)
{
    Console.WriteLine("Sorry, Apartment at {0} or at num {1}", newApartment.StreetName,
        newApartment.HouseNum);

}
else
{

    //print the details of apartment1
}

My XML is:

<?xml version="1.0" encoding="utf-8"?>
<Apartments>
  <Apartment street_name="sumsum">
    <Huose_Num>13</Huose_Num>
    <Num_Of_Rooms>4</Num_Of_Rooms>
    <Price>10000</Price>
    <Flags>
      <Elevator>true</Elevator>
      <Floor>1</Floor>
      <parking_spot>true</parking_spot>
      <balcony>true</balcony>
      <penthouse>true</penthouse>
      <status_sale>true</status_sale>
    </Flags>
  </Apartment>
</Apartments>

Upvotes: 0

Views: 105

Answers (4)

theDarse
theDarse

Reputation: 737

appatmentExist is an IEnumerable so to access the individual items within it use List indexing to access an individual element

Comsole.Writeline(appartmentExist.toList()[0].StreetName);

will print the streetname for the first element found in the query above

Upvotes: -2

howardlo
howardlo

Reputation: 1459

Try this:

var xml = @"<?xml version=""1.0"" encoding=""utf-8""?>
<Apartments>
  <Apartment street_name=""sumsum"">
    <Huose_Num>13</Huose_Num>
    <Num_Of_Rooms>4</Num_Of_Rooms>
    <Price>10000</Price>
    <Flags>
      <Elevator>true</Elevator>
      <Floor>1</Floor>
      <parking_spot>true</parking_spot>
      <balcony>true</balcony>
      <penthouse>true</penthouse>
      <status_sale>true</status_sale>
    </Flags>
  </Apartment>
</Apartments>
";

var apartmentXml = XElement.Parse( xml );
//apartmentXml.Dump(); // This is a linqpad feature

var new_street = "sumsum";
var new_house_num = "13";


var match_apartment = apartmentXml.Elements().Where (x => x.Attribute("street_name").Value ==  new_street && x.Element("Huose_Num").Value == new_house_num );
//match_apartment.Dump();

if (match_apartment.Count() < 1 )
{
    Console.WriteLine("Sorry, Apartment at {0} or at num {1}", new_street,
        new_house_num);

}
else
{
    foreach( var x in match_apartment.Elements() )
    {
        Console.WriteLine("{0} | {1}", x.Name, x.Value );
    }
}

Upvotes: 0

MarcinJuraszek
MarcinJuraszek

Reputation: 125660

  1. You LINQ query returns IEnumerable<XElement> If you expect it to return more then one element you can use foreach loop to print the elementss, if there is only one result you can call .Single() extension method to get the XElement, not collection:

  2. Casting XElement to string is safer then using XElement.Value property, because it will not throw NullReferenceException when element does not exist. You should also use (int)XElement cast and compare numbers instead of XElement.Value and comparing it to string representation of a number.

  3. You should not use Descendants method, Use Elements instead. It will make your query faster because only elements that need to be searched will be processed.

  4. You should call FirstOrDefault and check if result is null instead of using Any and then another First call. It will prevent your query from execution twice.

  5. Instead of returning apartment1.Value, which is a string, return apartment1 itself. It will be XElement and you'll be able to get into it's content later when it's necessary.

    var apartmentExist =
        from apartment1 in apartmentXml.Root.Elements("Apartment")
        where ((string)apartment1.Attribute("street_name") == newApartment.StreetName) &&
          ((int)apartment1.Element("Huose_Num") == newApartment.HouseNum)
        select apartment1;
    
    var apartment = apartmentExist.FirstOrDefault();
    
    if (apartment == null)
    {
        Console.WriteLine("Sorry, Apartment at {0} or at num {1}", newApartment.StreetName, newApartment.HouseNum);
    }
    else
    {
        // you can use apartment variable here. It's an XElement
        var huoseNum = (string)apartment.Element("Huose_Num");
    
        // flags
        foreach(var flag in apartment.Elements("Flags"))
        {
            var name = flag.Name;
            var value = (string)flag;
        }
    }
    

Upvotes: 5

Selman Gen&#231;
Selman Gen&#231;

Reputation: 101731

You can do it with one linq query like this:

var apartment =
(from a in apartmentXml.Descendants("Apartment")
where (a.Attribute("street_name").Value == newApartment.StreetName) &&
      (a.Element("Huose_Num").Value == newApartment.HouseNum.ToString())
select new { 
      street_name = a.Attribute("street_name").Value,
      Huose_Num = a.Element("Huose_Num").Value,
      Num_Of_Rooms = a.Element("Num_Of_Rooms").Value,
      Price = a.Element("Price").Value,
      Flags = (from f in a.Element("Flags")
                  select new { 
                    Elevator = f.Element("Elevator").Value,
                    Floor =  f.Element("Floor").Value,
                    parking_spot = f.Element("Floor").Value,
                    balcony = f.Element("balcony").Value,
                    penthouse = f.Element("penthouse").Value,
                    status_sale = f.Element("status_sale").Value
                    })
                 }).FirstOrDefault();

if(aparment == null) 
{
   Console.WriteLine("Sorry, Apartment at {0} or at num {1}", newApartment.StreetName,
    newApartment.HouseNum);
} 
else 
{
   Console.WriteLine(apartment.street_name);
   Console.WriteLine(apartment.Huose_Num);
   Console.WriteLine(apartment.Num_Of_Rooms);
   Console.WriteLine(apartment.Price);
   Console.WriteLine(apartment.street_name);

   Console.WriteLine(apartment.Flags.Elevator);
   Console.WriteLine(apartment.Flags.Floor);
   Console.WriteLine(apartment.Flags.parking_spot);
   Console.WriteLine(apartment.Flags.balcony);
   Console.WriteLine(apartment.Flags.penthouse);
   Console.WriteLine(apartment.Flags.status_sale);

}

Upvotes: 0

Related Questions