Cyberherbalist
Cyberherbalist

Reputation: 12319

What is wrong with my LINQ here? Doing what MSDN says, but

I'm trying to get an understanding of LINQ, and starting out on the MSDN page:

http://msdn.microsoft.com/library/bb308960.aspx#xlinqoverview_topic2f

Here, it references some sample XML

<contacts>
  <contact>
    <name>Patrick Hines</name>
    <phone type="home">206-555-0144</phone>
    <phone type="work">425-555-0145</phone>
    <address>
      <street1>123 Main St</street1>
      <city>Mercer Island</city>
      <state>WA</state>
      <postal>68042</postal>
    </address>
    <netWorth>10</netWorth>
  </contact>
  <contact>...

and says that the following will pump out a list of "phone" elements:

XElement contacts = XElement.Load(@"C:\Projects\ALL_MY_PROJECTS\LINQ_Noodling\UI\Contacts.xml");
foreach (x in contact.Elements("phone")) {
    Console.WriteLine(x);
}

like this:

<phone>206-555-0144</phone>
<phone>425-555-0145</phone>

Except it doesn't. I get nothing whatever. If I replace "phone" in the above with "contact" I get all the contacts (including "name" "phone" "address" and all the child elements), but that is it. It wouldn't be the last time that MSDN provided misleading or incorrect information, but the info as presented looks correct and logical.

Upvotes: 0

Views: 81

Answers (3)

Anon.
Anon.

Reputation: 59993

<phone> is a child element of <contact>, not the root element. If you look at the MSDN examples, note that they're calling Elements on one particular contact element.

You can chain Elements calls* to get further children:

foreach(XElement x in contacts.Elements("contact").Elements("phone"))

*if we were being nitpicky, it's not really chaining the same function, but IEnumerable<XObject>::Elements() acts pretty much how we expect it to anyway.

Upvotes: 4

Matti Virkkunen
Matti Virkkunen

Reputation: 65126

I think you should pay more attention before claiming that something another person wrote is wrong.

The part in which they do

foreach (x in contact.Elements("phone")) {
    Console.WriteLine(x);
}

Is preceded by:

For example, you might have the following XML loaded into an XElement called contact:

<contact>
   Met in 2005.
   <name>Patrick Hines</name>
   <phone>206-555-0144</phone>
   <phone>425-555-0145</phone>
   <!--Avoid whenever possible-->
</contact>

And your XML file doesn't match that. Elements only finds direct children of the element. So using the XML file you provided, the correct way to access the phone numbers (of everyone in the file) would be

XElement contacts = XElement.Load(@"C:\Projects\ALL_MY_PROJECTS\LINQ_Noodling\UI\Contacts.xml");
foreach (x in contacts.Elements("contact").Elements("phone")) {
    Console.WriteLine(x);
}

Upvotes: 2

Femaref
Femaref

Reputation: 61437

You are trying to access a child of a child of contacts. You'd have to do:

XElement contacts = XElement.Load(@"C:\Projects\ALL_MY_PROJECTS\LINQ_Noodling\UI\Contacts.xml");

foreach (x in contact.Elements("contact")) {
    Console.WriteLine(x.Element("phone"));
}

contacts is the root of the xml, contact is a child, and phone is a child of contact. The x in your loop is a contact node, on which you need to access its children.

Upvotes: 1

Related Questions