2013-10-14 3 views
1

У меня есть два XML-файла, OriginalXML и UpdatesXML, которые мне нужно объединить и сохранить только последние изменения. Мои пользователи по существу получают копию OriginalXML, вносят изменения, а затем отправляют обновления веб-службе. Мне нужно только обновить OriginalXML узлами, которые новее в UpdatesXML.C# объединить только XML последний узел

я могу перебирать узлы в UpdatesXML, сделайте поиск в OriginalXML на матч, проверить метку времени и заменить его, если обновления новее: (что-то вроде)

var OriginalXML = XDocument.Load("Original.xml"); 
var UpdatesXML = XDocument.Load("Updates.xml"); 

foreach (XElement WigitNode in UpdatesXML.Descendants("Wigit")) 
{ 
    //Find the corresponding OriginalXML node based on the Wigit/Subnode1/Id attribute 
    //Replace Original/Wigit with Updates/Wigit if Updates/Wigit/Editstamp/Timestamp attribute is later in Updates than Original 
} 

Всю эту вещь кажется довольно неуклюжим для меня, особенно если у Updates.xml много узлов. Мой вариант использования, вероятно, десятки за раз, поэтому это может быть не проблема, но кажется неэффективной. Есть ли простое преобразование XPath или xslt или что-то, что было бы быстрее или эффективнее?

Мой XML выглядит следующим образом: Original.xml:

<?xml version="1.0" encoding="utf-8"?> 
<Root> 
    <Wigit> 
    <EditStamp UserId="timmy" Timestamp="2013-09-13T20:22:00" /> 
    <Subnode1 Id="A" /> 
    </Wigit> 
    <Wigit> 
    <EditStamp UserId="phil" Timestamp="2013-09-13T21:51:00" /> 
    <Subnode1 Id="B" /> 
    </Wigit> 
    <Wigit> 
    <EditStamp UserId="biff" Timestamp="2013-10-13T21:51:00" /> 
    <Subnode1 Id="C" /> 
    </Wigit> 
</Root> 

Updates.xml:

<?xml version="1.0" encoding="utf-8"?> 
<Root> 
    <Wigit> 
    <EditStamp UserId="frank" Timestamp="2013-10-13T22:00:00" /> 
    <Subnode1 Id="A" /> 
    </Wigit> 
</Root> 

И желаемый результат:

<?xml version="1.0" encoding="utf-8"?> 
<Root> 
    <Wigit> 
    <EditStamp UserId="frank" Timestamp="2013-10-13T22:00:00" /> 
    <Subnode1 Id="A" /> 
    </Wigit> 
    <Wigit> 
    <EditStamp UserId="phil" Timestamp="2013-09-13T21:51:00" /> 
    <Subnode1 Id="B" /> 
    </Wigit> 
    <Wigit> 
    <EditStamp UserId="biff" Timestamp="2013-10-13T21:51:00" /> 
    <Subnode1 Id="C" /> 
    </Wigit> 
</Root> 

UPDATE: 10 -15-2013

Я сделал некоторые возился с помощью кода Abhijeet Патела ниже и пришел с этим:

var query = from o in docOriginal.Element("Root").Elements("Wigit") 
      from u in docUpdate.Element("Root").Elements("Wigit") 
      let x = docUpdate.Element("Root") 
           .Elements("Wigit") 
           .SingleOrDefault(e => (e.Element("Subnode1").Attribute("id").Value ==  o.Element("Subnode1").Attribute("id").Value && 
                 DateTime.Parse(e.Element("EditStamp").Attribute("Timestamp").Value).Ticks > DateTime.Parse(o.Element("EditStamp").Attribute("Timestamp").Value).Ticks)) ?? o 
      select x; 
XDocument merged = new XDocument(new XElement("Root", query)); 
return merged; 

Это дает правильный результат, за исключением, что каждый узел дублируется:

<Root> 
    <Wigit> 
    <EditStamp UserId="frank" Timestamp="2013-10-13T22:00:00" /> 
    <Subnode1 Id="SomeNewThing" /> 
    </Wigit> 
    <Wigit> 
    <EditStamp UserId="frank" Timestamp="2013-10-13T22:00:00" /> 
    <Subnode1 Id="SomeNewThing" /> 
    </Wigit> 
    <Wigit> 
    <EditStamp UserId="phil" Timestamp="2013-09-13T21:51:00" /> 
    <Subnode1 Id="B" /> 
    </Wigit> 
    <Wigit> 
    <EditStamp UserId="phil" Timestamp="2013-09-13T21:51:00" /> 
    <Subnode1 Id="B" /> 
    </Wigit> 
    <Wigit> 
    <EditStamp UserId="biff" Timestamp="2013-10-13T21:51:00" /> 
    <Subnode1 Id="C" /> 
    </Wigit> 
    <Wigit> 
    <EditStamp UserId="biff" Timestamp="2013-10-13T21:51:00" /> 
    <Subnode1 Id="C" /> 
    </Wigit> 
</Root> 

Любые намеки о том, как не дублировать результаты?

Обновление 10-16-2013:

Причина я получаю повторяющиеся результаты потому, что документ обновления я использовал два узла. Код должен обрабатывать сразу несколько изменений, обновляя только узлы с большей меткой времени.

string update = @"<?xml version='1.0' encoding='utf-8'?> 
<Root> 
    <Wigit id='A'> 
    <EditStamp UserId='frank' Timestamp='2013-10-13T22:00:00' /> 
    <Subnode1 Id='SomeNewThing' /> 
    </Wigit> 
    <Wigit id='B'> 
    <EditStamp UserId='yomamma' Timestamp='2013-09-10T21:51:00' /> 
    <Subnode1 Id='B' /> 
    </Wigit> 
</Root>"; 

ответ

2

Попробуйте это:

  string original = @"<?xml version='1.0' encoding='utf-8'?> 
          <Root> 
           <Wigit> 
            <EditStamp UserId='timmy' Timestamp='2013-09-13T20:22:00' /> 
            <Subnode1 Id='A' /> 
           </Wigit> 
           <Wigit> 
            <EditStamp UserId='phil' Timestamp='2013-09-13T21:51:00' /> 
            <Subnode1 Id='B' /> 
           </Wigit> 
           <Wigit> 
            <EditStamp UserId='biff' Timestamp='2013-10-13T21:51:00' /> 
            <Subnode1 Id='C' /> 
           </Wigit> 
          </Root>"; 

     string update = @"<?xml version='1.0' encoding='utf-8'?> 
         <Root> 
          <Wigit> 
           <EditStamp UserId='frank' Timestamp='2010-10-13T22:00:00' /> 
           <Subnode1 Id='A' /> 
          </Wigit> 
          <Wigit id='B'> 
           <EditStamp UserId='yomamma' Timestamp='2013-09-09T21:51:00' /> 
           <Subnode1 Id='B' /> 
          </Wigit> 
        </Root>"; 

     XDocument docOriginal = XDocument.Parse(original); 
     XDocument docUpdate = XDocument.Parse(update); 

     var query = from o in docOriginal.Element("Root").Elements("Wigit") 
        let x = docUpdate.Element("Root") 
            .Elements("Wigit") 
            .SingleOrDefault(e => 
             e.Element("Subnode1").Attribute("Id").Value == o.Element("Subnode1").Attribute("Id").Value 
             && (DateTime.Parse(e.Element("EditStamp").Attribute("Timestamp").Value) > DateTime.Parse(o.Element("EditStamp").Attribute("Timestamp").Value)) 
            ) ?? o 
        select x; 
     XDocument merged = new XDocument(new XElement("Root", query)); 
     Console.WriteLine(merged.ToString()); 
+0

Это действительно очень близко к тому, что мне нужно одна небольшая проблема является результатом этого запроса имеет каждый узел в его собственном узле (и пугающе просто!). ' ... – nickvans

+0

Надзор с моей стороны во время отладки. Я обновил ответ. Как правило, выбор в запросе Linq необходимо сделать «выбрать x». Попробуйте сейчас :-) –

+0

Ты мой герой! Большое вам спасибо за помощь! – nickvans

Смежные вопросы