Как эффективно сравнить два больших файла XML по пунктам? - PullRequest
2 голосов
/ 02 декабря 2010

Я планирую реализовать метод для сравнения двух больших файлов XML (но менее 10 000 строк элементов для каждого из них).

Метод ниже работает, но он не очень хорошо, когда файл более 100 строк. Это начинается очень медленно. Как я могу найти более эффективное решение. Возможно, нужен дизайн программирования на высоком C # или лучший алгоритм в C # и обработке XML.

Спасибо за ваши комментарии заранее.

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

мой XML-файл как этот. Два XML-файла одинакового стиля. За исключением некоторого времени один из них может быть изменен моим приложением. Вот почему мне нужно сравнить их, если они изменены.

<?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>

Ответы [ 3 ]

1 голос
/ 02 декабря 2010

XmlDocument и связанные с ним классы (XmlNode, ...) не очень быстро обрабатывают XML.Вместо этого попробуйте XmlTextReader.

Также вы вызываете docEvent_Alarm.Load(xmlFile_Event); и docConfAddition_Alarm.Load(xmlFile_ConfAddition); каждую итерацию родительского цикла - это не хорошо.Если ваши xmlFile_Event и xmlFile_ConfAddition являются постоянными в течение всей обработки - лучше инициализировать их перед основным циклом.

1 голос
/ 02 декабря 2010

Вы пытались использовать класс Microsoft XmlDiff? Смотри http://msdn.microsoft.com/en-us/library/aa302294.aspx

1 голос
/ 02 декабря 2010

Кажется, что ключом является ALID / @ alid, поэтому первое, что я хотел бы сделать (до foreach (XmlNode xn in xnList)), это построить словарь (предполагая, что он уникален) поверх значений docEvent_Alarm.SelectNodes("/Equipment/Alarms/ALID") @alid - тогда вы может сделать большую часть работы без O (n * m) производительности - это будет больше O (n + m) (что является большой разницей).

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

тогда вы можете использовать:

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