views:

208

answers:

2

My xml looks like:

<nodes>
<node name="somekey">
<item name="subject">blah</item>
<item name="body">body</item>
</node>
</nodes>

And my code so far is:

XDocument doc = XDocument.Load(HttpContext.Current.Server.MapPath(String.Format("~/files/{0}/text.xml", "en")));

if (doc != null)
{
    XElement element = doc.Elements().Where(e => e.Elements().Any() && e.Attribute("name").Value == "someKey").First();
}

I am getting an error saying:

Sequence contains no elements

Is my query wrong?

I stepped through the code, and it errors out on the line with XElement..

+1  A: 

You want something like this:

var element = doc.Descendants("node").Where(x => x.Attribute("name") != null && x.Attribute("name").Value == "somekey").FirstOrDefault();

Edit: Edited to grab first element from result;

Matt Dearing
ok it worked if I remove the "node", since descendants is being called at the root node.
Blankman
+1  A: 

You could also use:

var element = doc.Elements()
                 .Elements()
                 .Where(e => (e.Elements().Any() 
                              && e.Attribute("name").Value == "somekey"))
                 .First();

Explanation:

The doc.Elements() grabs the root element, which is nodes. Then the .Elements() selects the child elements of that, which is just one, node. The .Where() is then performed on that nodeset, which is what you want. The lambda selects those elements that have child elements, and also have an attribute "name" with value "somekey".

Your original code was not getting the Child-of-Child-elements. Hence the original result set was empty.

You could also do this with .Descendants() but that feels a little sloppy and loose, to me.

Cheeso