0

次の構造の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"));
4

2 に答える 2

1

「何も返さない」と「例外が発生する」は大きく異なります。

問題はここにあります:

 where node.Descendants(nsohr + "code")
           .Single().Attribute("codeContainer").Value.Equals("CCVal1")

を使用しています。これは、要素が 1 つだけない場合に例外をスローすることSingle()文書化されています。案の定、その例外があります。

ただし、クエリははるかに簡単にすることができます。

var res = xDoc.Descendants(nsohr + "workDomain")
              .Descendants(nsohr + "event")
              .Where(x => x.Elements("code")
                           .Any(x => (string) x.Attribute("codeContainer") == "CCVal1"
                                  && (string) x.Attribute("code") == "4567"));

code(これは、が常に の直接の子であると仮定しています。そうでない場合は、代わりに をevent使用できます。)DescendantsElements

つまり、少なくとも 1 つの子子要素が関連する属性を持つ要素eventの子孫を見つけます。workDomaincode

于 2013-06-20T17:54:27.453 に答える
0

.Single()要素数が 1 以外のコレクションを呼び出すと、常に例外が発生します。

node.Descendants(nsohr + "code").Single()おそらく例外をスローしているセグメントです。

あなたのコレクションが(理論的には)1つの要素しか持たないことになっている場合は、使用しないでください.Single()

しかし、あなたは自分に合ったクエリを見つけたようです。他に問題はありますか?


今後の参考のために、要素の 1 つだけを探している場合は、Elementまたはのようなメソッドを使用できますDescendant

要素のコレクションに対してElementsandを呼び出すこともできます。Descendants

于 2013-06-20T17:54:37.110 に答える