2010-12-02 55 views
2

Je prévois d'implémenter une méthode pour comparer deux gros fichiers XML (mais moins de 10 000 lignes d'éléments pour chacun des autres).Comment comparer efficacement deux gros fichiers XML élément par élément?

La méthode ci-dessous fonctionne, mais elle ne fonctionne pas bien lorsque le fichier dépasse 100 lignes. Ça commence très lentement. Comment puis-je trouver une solution plus efficace? Peut-être besoin de haute programmation de programmation C# ou mieux Algorithme en C# & Manipulation XML.

Merci pour vos commentaires à l'avance.

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

mon fichier XML comme ceci. Les deux fichiers XML sont de même style. Sauf quelques temps l'un d'eux peut être modifié par mon application. C'est pourquoi j'ai besoin de les comparer s'ils sont modifiés.

<?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, les itérations imbriquées ne sont pas la solution lorsque vous essayez de comparer les performances. Nettoyez votre code. –

Répondre

1

Le « ALID/@ alid » semble être la clé, la première chose que je ferais (avant foreach (XmlNode xn in xnList)) est de construire un dictionnaire (en supposant qu'elle est unique) sur les valeurs docEvent_Alarm.SelectNodes("/Equipment/Alarms/ALID") @alid - vous peut faire la plupart du travail sans la performance O (n * m) - ce sera plus O (n + m) (ce qui est une grande différence).

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

vous pouvez utiliser:

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

'var' Vient de .net 2.0? Je dois basé sur .net 2.0. –

+1

@Nano HE, alors il suffit de remplacer var avec le nom du type, 'Dictionary ' dans ce cas. – steinar

+1

@Nano - 'var' est C# 3.0, qui peut être utilisé pour cibler n'importe quelle version .NET; mais @steiner a raison; si vous utilisez C# 2.0 (VS2005), utilisez simplement Dictionary ' –

1

XmlDocument et les classes connexes (XmlNode, ...) ne sont pas assez rapide dans le traitement xml. Essayez plutôt XmlTextReader.

Aussi vous appelez docEvent_Alarm.Load(xmlFile_Event); et docConfAddition_Alarm.Load(xmlFile_ConfAddition); chaque itération de la boucle parentale - ce n'est pas bon. Si votre xmlFile_Event et xmlFile_ConfAddition sont persistants pendant tout le traitement - mieux l'initialiser avant la boucle principale.