2010-12-02 15 views
2

Ich plane, eine Methode zu implementieren, um zwei große XML-Dateien zu vergleichen (aber weniger als 10.000 Elementlinien für jedes andere).Wie zwei große XML-Dateien Element für Element effizient vergleichen?

Die folgende Methode funktioniert, aber es ist nicht gut, wenn die Datei mehr als 100 Zeilen. Es beginnt sehr langsam. Wie kann ich eine effizientere Lösung finden? Vielleicht brauchen High C# -Programmierung Design oder besser Algorithmus in C# & XML-Behandlung.

Vielen Dank für Ihre Kommentare im Voraus.

//Remove the item which not in Event Xml and ConfAddition Xml files 
XmlDocument doc = new XmlDocument(); 
doc.Load(xmlFile_AlarmSettingUp); 

bool isNewAlid_Event = false; 
bool isNewAlid_ConfAddition = false; 
int alid = 0; 

XmlNodeList xnList = doc.SelectNodes("/Equipment/AlarmSettingUp/EnabledALIDs/ALID"); 

foreach (XmlNode xn in xnList) 
{       
    XmlAttributeCollection attCol = xn.Attributes; 

    for (int i = 0; i < attCol.Count; ++i) 
    { 
     if (attCol[i].Name == "alid") 
     { 
      alid = int.Parse(attCol[i].Value.ToString()); 
      break; 
     } 
    } 

    //alid = int.Parse(attCol[1].Value.ToString()); 

    XmlDocument docEvent_Alarm = new XmlDocument(); 
    docEvent_Alarm.Load(xmlFile_Event); 
    XmlNodeList xnListEvent_Alarm = docEvent_Alarm.SelectNodes("/Equipment/Alarms/ALID"); 
    foreach (XmlNode xnEvent_Alarm in xnListEvent_Alarm) 
    { 
     XmlAttributeCollection attColEvent_Alarm = xnEvent_Alarm.Attributes; 
     int alidEvent_Alarm = int.Parse(attColEvent_Alarm[1].Value.ToString()); 
     if (alid == alidEvent_Alarm) 
     { 
      isNewAlid_Event = false; 
      break; 
     } 
     else 
     { 
      isNewAlid_Event = true; 
      //break; 
     } 
    } 

    XmlDocument docConfAddition_Alarm = new XmlDocument(); 
    docConfAddition_Alarm.Load(xmlFile_ConfAddition); 
    XmlNodeList xnListConfAddition_Alarm = docConfAddition_Alarm.SelectNodes("/Equipment/Alarms/ALID"); 
    foreach (XmlNode xnConfAddition_Alarm in xnListConfAddition_Alarm) 
    { 
     XmlAttributeCollection attColConfAddition_Alarm = xnConfAddition_Alarm.Attributes; 
     int alidConfAddition_Alarm = int.Parse(attColConfAddition_Alarm[1].Value.ToString()); 
     if (alid == alidConfAddition_Alarm) 
     { 
      isNewAlid_ConfAddition = false; 
      break; 
     } 
     else 
     { 
      isNewAlid_ConfAddition = true; 
      //break; 
     } 
    }       

    if (isNewAlid_Event && isNewAlid_ConfAddition) 
    { 
     // Store the root node of the destination document into an XmlNode 
     XmlNode rootDest = doc.SelectSingleNode("/Equipment/AlarmSettingUp/EnabledALIDs"); 
     rootDest.RemoveChild(xn); 
    } 

} 
doc.Save(xmlFile_AlarmSettingUp); 

meine XML-Datei als dies. Die zwei XML-Dateien haben denselben Stil. Außer einiger Zeit kann einer von ihnen von meiner App geändert werden. Deshalb muss ich sie vergleichen, wenn sie geändert werden.

<?xml version="1.0" encoding="utf-8"?> 
<Equipment xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
    <Licence LicenseId="" LicensePath="" /> 
    <!--Alarm Setting Up XML File--> 
    <AlarmSettingUp> 
    <EnabledALIDs> 
     <ALID logicalName="Misc_EV_RM_STATION_ALREADY_RESERVED" alid="536870915" alcd="7" altx="Misc_Station 1 UnitName 2 SlotId already reserved" ceon="Misc_AlarmOn_EV_RM_STATION_ALREADY_RESERVED" ceoff="Misc_AlarmOff_EV_RM_STATION_ALREADY_RESERVED" /> 
     <ALID logicalName="Misc_EV_RM_SEQ_READ_ERROR" alid="536870916" alcd="7" altx="Misc_Sequence ID 1 d step 2 d read error for wafer in 3 UnitName 4 SlotId" ceon="Misc_AlarmOn_EV_RM_SEQ_READ_ERROR" ceoff="Misc_AlarmOff_EV_RM_SEQ_READ_ERROR" /> 
... 
... 
... 
    </EnabledALIDs> 
    </AlarmSettingUp> 
</Equipment> 
+1

Ugh, verschachtelte Iterationen sind nicht der richtige Weg, wenn Sie versuchen, die Leistung zu vergleichen. Säubern Sie Ihren Code. –

Antwort

1

Die „ALID/@ alid“ scheint Ihr Schlüssel zu sein, so dass das erste, was ich (vor foreach (XmlNode xn in xnList)) tun würde, ist ein Wörterbuch bauen (vorausgesetzt, diese einzigartig ist) über die docEvent_Alarm.SelectNodes("/Equipment/Alarms/ALID") @alid Werte - Sie dann kann die meiste Arbeit ohne O (n * m) Leistung machen - es wird mehr O (n + m) sein (was ein großer Unterschied ist).

var lookup = new Dictionary<string, XmlElement>(); 
foreach(XmlElement el in docEvent_Alarm.SelectNodes("/Equipment/Alarms/ALID")) { 
    lookup.Add(el.GetAttribute("alid"), el); 
} 

dann können Sie verwenden:

XmlElement other; 
if(lookup.TryGetValue(otherKey, out other)) { 
    // exists; element now in "other" 
} else { 
    // doesn't exist 
} 
+0

'var' Kommt von .net 2.0? Ich muss auf .net 2.0 basieren. –

+1

@Nano HE, dann einfach var durch den Typnamen ersetzen, 'Dictionary ' in diesem Fall. – steinar

+1

@Nano - 'var' ist C# 3.0, das verwendet werden kann, um eine beliebige .NET-Version anzusprechen; aber @steiner hat recht; Wenn Sie C# 2.0 (VS2005) verwenden, verwenden Sie einfach Dictionary ' –

1

XmlDocument und verwandte Klassen (XmlNode, ...) in die XML-Verarbeitung nicht sehr schnell sind. Versuchen Sie stattdessen XmlTextReader.

Auch Sie rufen docEvent_Alarm.Load(xmlFile_Event); und docConfAddition_Alarm.Load(xmlFile_ConfAddition); jede Wiederholung der elterlichen Schleife - es ist nicht gut. Wenn Ihre xmlFile_Event und xmlFile_ConfAddition während der gesamten Verarbeitung persistent sind - besser, es vor der Hauptschleife zu initialisieren.

Verwandte Themen