質問

2 つの XElement セットを単一の一意の要素セットに結合する必要があります。.Union() 拡張メソッドを使用すると、結合の代わりに「すべて結合」が得られます。何かが足りないのでしょうか?

var elements = xDocument.Descendants(w + "sdt")
                   .Union(otherDocument.Descendants(w + "sdt")
                   .Select(sdt =>
                       new XElement(
                           sdt.Element(w + "sdtPr")
                               .Element(w + "tag")
                               .Attribute(w + "val").Value,
                           GetTextFromContentControl(sdt).Trim())
                   )
               );
役に立ちましたか?

解決

あなたの最初の衝動はほぼ正しかったです。:) デビッド・B, 等価性を定義する方法を LINQ に正確に伝えず、それに大量の XElement を与えると、参照によってそれらが比較されます。幸いなことに、IEqualityComparer‹XElement› (基本的に、定義に従って 2 つの XElement が等しい場合は true を返し、そうでない場合は false を返す Equals メソッドを持つオブジェクトと、XElement を受け取る GetHashCode メソッドを持つオブジェクト) を指定することで、異なる基準を使用するように指示できます。等価基準に基づいてハッシュ コードを返します)。

例えば:

var elements = xDocument.Descendants(w + "sdt")
               .Union(otherDocument.Descendants(w + "sdt", new XElementComparer())
               .RestOfYourCode

...

プロジェクト内の別の場所

public class XElementComparer : IEqualityComparer‹XElement› {
   public bool Equals(XElement x, XElement y) {
     return ‹X and Y are equal according to your standards›;
}


 public int GetHashCode(XElement obj) {
     return ‹hash code based on whatever parameters you used to determine        
            Equals. For example, if you determine equality based on the ID 
            attribute, return the hash code of the ID attribute.›;

 }

 }

注記:家にフレームワークがないため、正確なコードはテストされていません。IEqualityComparer コードは次のとおりです。 ここ (2 番目の投稿まで下にスクロールします)。

他のヒント

それはあなたがその結論に来るために使用しているが何であるかを見ることなく、あなたの「左の参加」の観察のトラブルシューティングを行うには本当に難しいです。ここでは暗闇の中で私のショットがあります。

XDocument doc1 = XDocument.Parse(@"<XML><A/><C/></XML>");
XDocument doc2 = XDocument.Parse(@"<XML><B/><C/></XML>");
//
var query1 = doc1.Descendants().Union(doc2.Descendants());
Console.WriteLine(query1.Count());
foreach (XElement e in query1) Console.WriteLine("--{0}",e.Name);

6
--XML
--A
--C
--XML
--B
--C
//
var query2 = doc1.Descendants().Concat(doc2.Descendants())
  .GroupBy(x => x.Name)
  .Select(g => g.First());
Console.WriteLine(query2.Count());
foreach (XElement e in query2) Console.WriteLine("--{0}", e.Name);

4
--XML
--A
--C
--B

(本当にあるのxmlに何LINQである)オブジェクトへのLINQでは、参照型に対する連合は、重複をテストするために参照の等価を使用しています。 XElementは、参照型である。

私は仕事に以下を得ることができたが、それは非常に醜いです。

var elements = xDocument.Descendants(w + "sdt")
                   .Concat(otherDocument.Descendants(w + "sdt")
                               .Where(e => !xDocument.Descendants(w + "sdt")
                                               .Any(x => x.Element(w + "sdtPr")
                                                             .Element(w + "tag")
                                                             .Attribute(w + "val").Value ==
                                                         e.Element(w + "sdtPr")
                                                             .Element(w + "tag")
                                                             .Attribute(w + "val").Value)))
                   .Select(sdt =>
                       new XElement(
                           sdt.Element(w + "sdtPr")
                               .Element(w + "tag")
                               .Attribute(w + "val").Value,
                           GetTextFromContentControl(sdt).Trim())
                   )
               );

確かに、より良い方法がなければならない。

このようなことについては何?

var xDoc = from f in xDocument.Descendants(w + "sdt")
    select new {xNode = f, MatchOn = f.Element(w + "sdtPr").Element(w + "tag").Attribute(w + "val").Value };

var oDoc = from o in otherDocument.Descendants(w + "sdt")
    select new {MatchOn = o.Element(w + "sdtPr").Element(w + "tag").Attribute(w + "val").Value };

var elements = from x in xDoc.Where(f => !oDoc.Any(o => o.MatchOn == f.MatchOn))
    select new XElement(x.MatchOn, GetTextFromContentControl(x.xNode).Trim());
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top