2016-06-06 5 views
2

i zwei XElements zu vergleichen versuche() wie folgt:Linq - XElement Vergleichen

XElement parentItems =

<tcm:ListItems xmlns:tcm="http://www.tridion.com/ContentManager/5.0"> 
    <tcm:Item Title="070_Page" Modified="2016-01-06T18:08:36" CP1="-6185, Intro" CP2="-6182, Article Body" CP3="-14507, Article Body1" CP4="-14430, Article Body2" CP5="-14530, Article Body3" CP6="-7064, Article Body4" CP7="-14529, Article Body5" CP8="-7065, Article Body6" CPCount="8" /> 
    <tcm:Item Title="080_Page" Modified="2015-04-23T13:27:59" CP1="-6302, Intro" CP2="-6193, Article Body" CPCount="2" /> 
    <tcm:Item Title="Release Notes" Modified="2016-01-07T21:25:43" CP1="-6303, Release Notes Intro" CP2="-6196, Release Notes Article Body" CPCount="2" /> 
</tcm:ListItems> 

XElement childItems =

<tcm:ListItems xmlns:tcm="http://www.tridion.com/ContentManager/5.0"> 
    <tcm:Item Title="070_Page" Modified="2016-06-06T19:36:35" CP1="-6185, Intro" CP2="-6147, Media & Delivery Intro" CP3="-6182, Article Body" CP4="-14507, Article Body1" CP5="-14430, Article Body2" CP6="-14530, Article Body3" CP7="-7064, Article Body4" CP8="-14529, Article Body5" CP9="-7065, Article Body6" CPCount="9" /> 
    <tcm:Item Title="080_Page" Modified="2016-02-09T21:03:32" CP1="-6302, Intro" CP2="-6193, Article Body" CPCount="2" /> 
    <tcm:Item Title="Release Notes" Modified="2016-02-09T21:03:33" CP1="-6303, Release Notes Intro" CP2="-6196, Release Notes Article Body" CPCount="2" /> 
    <tcm:Item Title="Release Notes1" Modified="2016-03-09T22:00:13" CP1="-6303, Release Notes Intro" CP2="-6196, Release Notes Article Body" CPCount="2" /> 
</tcm:ListItems> 

ich mein Ergebnis sein soll (der erste hat einen anderen CPCount und der zweite ist ein neues Element in childItems):

XElement d iff =

<tcm:ListItems xmlns:tcm="http://www.tridion.com/ContentManager/5.0"> 
    <tcm:Item Title="070_Page" Modified="2016-06-06T19:36:35" CP1="-6185, Intro" CP2="-6147, Media & Delivery Intro" CP3="-6182, Article Body" CP4="-14507, Article Body1" CP5="-14430, Article Body2" CP6="-14530, Article Body3" CP7="-7064, Article Body4" CP8="-14529, Article Body5" CP9="-7065, Article Body6" CPCount="9" /> 
    <tcm:Item Title="Release Notes1" Modified="2016-03-09T22:00:13" CP1="-6303, Release Notes Intro" CP2="-6196, Release Notes Article Body" CPCount="2" /> 
</tcm:ListItems> 

Ich habe XMLDiff API aber kein Glück versucht. Ich kann durchschleifen und die Ergebnisse bekommen, aber manchmal kann die Liste riesig sein (3000+). Gibt es einen besten Weg, damit umzugehen?

+0

Sie möchten also Title-Attribut als Schlüssel und andere Attribute verwenden - nur vergleichen, wenn vorhanden, und in der resultierenden Liste anzeigen, wenn nicht übereinstimmende oder fehlende Attribute? Sie sollten in der Lage sein, eine 'Dictionary >' zu verwenden, wobei der erste Schlüssel ein Elementtitel und der zweite Schlüssel der zu vergleichende Eigenschaftsname ist. Baue zwei davon, für links und rechts, dann vergleiche. – Neolisk

+0

Danke Neolisk ... Ja, Titel wird der Hauptfilter sein .. Andere Attribute können anders sein .. aber meine Ergebnisse sollten basieren auf: 1) CPCount 2) wenn es ein neues Element in Kind gibt, das doesn ' t existieren in Parent ist Wörterbuch ein richtiger Weg? Wird es eine schlechte Leistung geben ... Hat Linq so etwas wie Deepequals? https://msdn.microsoft.com/en-us/library/system.xml.linq.xnode.deepequals(v=vs.110).aspx – Harish

+0

Ich werde das untersuchen, wenn ich wieder zu Hause bin - werde versuchen Mache ein funktionierendes Codebeispiel für dich. – Neolisk

Antwort

1

Ok, hier ist der Code - in einer Konsolenanwendung erstellt mit VS2015 (könnte nicht optimal sein, aber es funktioniert - ich die beiden erwarteten Elemente am Ende bekommen - Refactoring als Hausaufgaben für Sie zu verlassen):

class Program 
{ 
    //this is just for convenient storage of all collected data 
    //also to avoid additional dictionary lookups and processing 
    internal class ElementAttributes 
    { 
     public XElement Element { get; set; } 
     public Dictionary<string, string> Attributes; 

     public ElementAttributes(XElement element) 
     { 
      this.Element = element; 
      this.Attributes = new Dictionary<string, string>(); 
     } 
    } 

    static void Main(string[] args) 
    { 
     //loading XML elements from embedded resources 
     XElement parentItems = XElement.Parse(ResourceXML.parentItems); 
     XElement childItems = XElement.Parse(ResourceXML.childItems); 

     XElement diff = XElement.Parse(@"<tcm:ListItems xmlns:tcm=""http://www.tridion.com/ContentManager/5.0"" ></tcm:ListItems>"); 

     var parentDictionary = BuildDictionary(parentItems); 
     var childDictionary = BuildDictionary(childItems); 

     //perform diff 
     foreach (string key in childDictionary.Keys) 
     { 
      ElementAttributes parentElementAttributes; 
      if (parentDictionary.TryGetValue(key, out parentElementAttributes)) 
      { 
       //found Title/key in parent, compare attributes 
       foreach (var childAttribute in childDictionary[key].Attributes) 
       { 
        var attributeName = childAttribute.Key; 
        var childAttributeValue = childAttribute.Value; 

        string parentAttributeValue; 
        if (parentElementAttributes.Attributes.TryGetValue(attributeName, out parentAttributeValue)) 
        { 
         //found attribute in parent, compare value 
         if(childAttributeValue == parentAttributeValue) 
         { 
          //values are equal, compare other attributes 
          continue; 
         } 
        } 

        //parent does not have this attribute OR 
        //different value in child -> show in diff 
        diff.Add(childDictionary[key].Element); 

        //do not compare other attributes 
        break; 
       } 

       //child may have missing attributes, which are in parent only 
       //NOTE: your example does not present a use case for this scenario 
       foreach (var parentAttribute in parentElementAttributes.Attributes) 
       { 
        string attributeName = parentAttribute.Key; 
        if (!childDictionary[key].Attributes.ContainsKey(attributeName)) 
        { 
         //attribute found in parent, but not in child 
         diff.Add(childDictionary[key].Element); 
         break; 
        } 
       } 
      } 
      else 
      { 
       //not found in parent, show in diff 
       diff.Add(childDictionary[key].Element); 
      } 
     } 
    } 


    private static Dictionary<string, ElementAttributes> BuildDictionary(XElement element) 
    { 
     XNamespace tcm = "http://www.tridion.com/ContentManager/5.0"; 

     var resultDictionary = new Dictionary<string, ElementAttributes>(); 
     foreach (XElement childElement in element.Elements(tcm + "Item")) 
     { 
      var attributeDictionary = new ElementAttributes(childElement); 
      foreach (XAttribute attribute in childElement.Attributes()) 
      { 
       string[] excludedColumns = {"Title", "Modified"}; 

       if (excludedColumns.Contains(attribute.Name.LocalName)) 
       { 
        continue; 
       } 

       attributeDictionary.Attributes.Add(attribute.Name.LocalName, attribute.Value); 
      } 
      resultDictionary.Add(childElement.Attribute("Title").Value, attributeDictionary); 
     } 
     return resultDictionary; 
    } 
} 
+1

Danke Neolisk. Dieser Code ist eine Schönheit :) .. – Harish