次の構造のxmlファイルがあります
....
<workDomain>
...
<event>some value</event>
.....
<event>
<code codeContainer="CCVal1" code="4567">
...
<code>
</event>
</workDomain>
コードの子を持たない単純なイベントではなく、コードの子を持つイベントに興味があります。
ただし、次の linq クエリを使用すると:
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;
何も返しません。つまり、foreach で res を反復しようとすると、「シーケンスには要素が含まれていません」という例外が発生します。
以下のような明示的な制約を通じて、イベントの子の存在を強制するとします。
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;
その後、すべてが期待どおりに機能します。なぜ私は追加しなければならないのですか?
node.Descendants(nsohr + "code").Count() > 0
? 子孫に対する制約は、子孫の存在を意味するべきか、そう思います。これは私には非常に不自然に感じます。ここで何が欠けていますか?
更新: Jon の例は、linq to xml の動作に関する私の誤解を理解するのに役立ちました。私はどういうわけか、ノードに配置した基準が、選択されるノードを決定するという印象を受けました (誤って) 物事が db クエリのように機能すると考えていました: db は sql を解析し、データを選択します。それらのメソッドを呼び出すための間違ったオブジェクトのメソッド。小さな修正を加えた Jon のスニペット (ここで Jon に何かが欠けていないと仮定して) は、期待どおりに動作します。
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"));