Why isn't this XElement query working on my xml
-
18-09-2019 - |
Question
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..
Solution
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;
OTHER TIPS
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.