There is an xml file with the following structure
....
<workDomain>
...
<event>some value</event>
.....
<event>
<code codeContainer="CCVal1" code="4567">
...
<code>
</event>
</workDomain>
I am interested in the event with code children, not the simple event without any code children.
However, if I use the following linq query:
var res = from node in xDoc.Descendants(nsohr + "workDomain").Single().Descendants(nsohr + "event")
where node.Descendants(nsohr + "code").Single().Attribute("codeContainer").Value.Equals("CCVal1")
&& node.Descendants(nsohr + "code").Single().Attribute("code").Value.Equals("4567")
select node;
returns nothing. That is I get: "Sequence contains no elements" exception if I attempt to iterate over res with foreach.
If I enforce the existence of children of event through an explicit constraint such as the one below:
var res = from node in xDoc.Descendants(nsohr + "workDomain").Single().Descendants(nsohr + "event")
where node.Descendants(nsohr + "code").Count() > 0
&& node.Descendants(nsohr + "code").Single().Attribute("codeContainer").Value.Equals("CCVal1")
&& node.Descendants(nsohr + "code").Single().Attribute("code").Value.Equals("4567")
select node;
Then everything works as expected. Why on earth do I have to add
node.Descendants(nsohr + "code").Count() > 0
? The constrains on descendants should imply their existence, or so I think. This feels very unnatural to me. What am I missing here?
Update: Jon's example helped me see my misunderstanding about the way linq to xml works. I was somehow under the impression that the criteria I've placed on the nodes would determine the nodes which will be selected (incorrectly) thinking things work like a db query: db parsing sql and selecting data etc... I simply ended up calling methods on wrong objects for calling those methods. Jon's snippet with a small fix (assuming I'm not missing something here Jon) works as expected:
var res = xDoc.Descendants(nsohr + "workDomain")
.Descendants(nsohr + "event")
.Where(x => x.Elements("code")
.Any(y => (string) y.Attribute("codeContainer") == "CCVal1"
&& (string) y.Attribute("code") == "4567"));