Reputation: 61
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
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
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
Reputation: 125660
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:
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.
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.
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.
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
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