Vra

Ek moet unie twee stelle XElements in 'n enkele, unieke stel elemente. Die gebruik van die .Union () uitbreiding metode, kry ek net 'n "unie al" in plaas van 'n vakbond. Mis ek iets?

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())
                   )
               );
Was dit nuttig?

Oplossing

Jou eerste impuls was byna korrek. :) Soos per David B , as jy nie LINQ vertel presies hoe jy gelykheid te definieer en gee dit dan 'n klomp van die XElements, dit sal hulle vergelyk word met verwysing . Gelukkig kan jy dit vertel aan verskillende kriteria gebruik deur die spesifiseer van 'n IEqualityComparer (basies, 'n voorwerp wat 'n het gelyk aan metode wat ware terugkeer IFF twee XElements gelyk volgens jou definisie en valse anders en 'n GetHashCode metode wat 'n XElement neem en gee 'n hash wetboek saamgestel gegrond op jou kriteria gelykheid).

Byvoorbeeld:

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

...

Iewers anders in jou projek

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.›;

 }

 }

Let wel: Ek het nie die raamwerk van die huis af, so die presiese kode is nie getoets en die IEqualityComparer kode is uit hier (gaan na tweede post).

Ander wenke

Dit is regtig moeilik om jou "links te sluit" waarneming op te los sonder om te sien wat dit is wat jy gebruik om daardie gevolgtrekking te kom. Hier is my skoot in die donker.

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

In linQ om voorwerpe (en dit is wat linQ aan xml regtig is), Unie teen verwysing tipes gebruik verwysing gelykheid te toets vir duplikate. XElement is 'n verwysing tipe.

Ek was in staat om die volgende te werk te kry, maar dit is nogal lelik:

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())
                   )
               );

Sekerlik moet daar 'n beter manier wees.

Wat van iets soos hierdie?

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());
Gelisensieer onder: CC-BY-SA met toeskrywing
Nie verbonde aan StackOverflow
scroll top