Note that there are some explanatory texts on larger screens.

plurals
  1. POC# combine XML latest node only
    primarykey
    data
    text
    <p>I've got two XML files, OriginalXML and UpdatesXML that I need to combine and retain only the latest changes. My users essentially get a copy of the OriginalXML, make edits then submit the updates to a web service. I need to only update the OriginalXML with nodes that are newer in the UpdatesXML.</p> <p>I can iterate over the nodes in the UpdatesXML, do a search of the OriginalXML for a match, check the timestamp and replace it if the updates is newer: (something like)</p> <pre><code>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 } </code></pre> <p>This whole thing seems rather clunky to me, especially if the Updates.xml has a lot of nodes. My use case is probably dozens at a time, so it may not be an issue, but it seems inefficient. Is there a straightforward XPath or xslt transform or something that would be faster or more efficient?</p> <p>My XML looks like this: Original.xml:</p> <pre><code>&lt;?xml version="1.0" encoding="utf-8"?&gt; &lt;Root&gt; &lt;Wigit&gt; &lt;EditStamp UserId="timmy" Timestamp="2013-09-13T20:22:00" /&gt; &lt;Subnode1 Id="A" /&gt; &lt;/Wigit&gt; &lt;Wigit&gt; &lt;EditStamp UserId="phil" Timestamp="2013-09-13T21:51:00" /&gt; &lt;Subnode1 Id="B" /&gt; &lt;/Wigit&gt; &lt;Wigit&gt; &lt;EditStamp UserId="biff" Timestamp="2013-10-13T21:51:00" /&gt; &lt;Subnode1 Id="C" /&gt; &lt;/Wigit&gt; &lt;/Root&gt; </code></pre> <p>Updates.xml:</p> <pre><code>&lt;?xml version="1.0" encoding="utf-8"?&gt; &lt;Root&gt; &lt;Wigit&gt; &lt;EditStamp UserId="frank" Timestamp="2013-10-13T22:00:00" /&gt; &lt;Subnode1 Id="A" /&gt; &lt;/Wigit&gt; &lt;/Root&gt; </code></pre> <p>And the desired output is:</p> <pre><code>&lt;?xml version="1.0" encoding="utf-8"?&gt; &lt;Root&gt; &lt;Wigit&gt; &lt;EditStamp UserId="frank" Timestamp="2013-10-13T22:00:00" /&gt; &lt;Subnode1 Id="A" /&gt; &lt;/Wigit&gt; &lt;Wigit&gt; &lt;EditStamp UserId="phil" Timestamp="2013-09-13T21:51:00" /&gt; &lt;Subnode1 Id="B" /&gt; &lt;/Wigit&gt; &lt;Wigit&gt; &lt;EditStamp UserId="biff" Timestamp="2013-10-13T21:51:00" /&gt; &lt;Subnode1 Id="C" /&gt; &lt;/Wigit&gt; &lt;/Root&gt; </code></pre> <p><strong>UPDATE: 10-15-2013</strong></p> <p>I did some fiddling using Abhijeet Patel's code below and came up with this:</p> <pre><code>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 =&gt; (e.Element("Subnode1").Attribute("id").Value == o.Element("Subnode1").Attribute("id").Value &amp;&amp; DateTime.Parse(e.Element("EditStamp").Attribute("Timestamp").Value).Ticks &gt; DateTime.Parse(o.Element("EditStamp").Attribute("Timestamp").Value).Ticks)) ?? o select x; XDocument merged = new XDocument(new XElement("Root", query)); return merged; </code></pre> <p>This gives the proper result except that every node is duplicated:</p> <pre><code>&lt;Root&gt; &lt;Wigit&gt; &lt;EditStamp UserId="frank" Timestamp="2013-10-13T22:00:00" /&gt; &lt;Subnode1 Id="SomeNewThing" /&gt; &lt;/Wigit&gt; &lt;Wigit&gt; &lt;EditStamp UserId="frank" Timestamp="2013-10-13T22:00:00" /&gt; &lt;Subnode1 Id="SomeNewThing" /&gt; &lt;/Wigit&gt; &lt;Wigit&gt; &lt;EditStamp UserId="phil" Timestamp="2013-09-13T21:51:00" /&gt; &lt;Subnode1 Id="B" /&gt; &lt;/Wigit&gt; &lt;Wigit&gt; &lt;EditStamp UserId="phil" Timestamp="2013-09-13T21:51:00" /&gt; &lt;Subnode1 Id="B" /&gt; &lt;/Wigit&gt; &lt;Wigit&gt; &lt;EditStamp UserId="biff" Timestamp="2013-10-13T21:51:00" /&gt; &lt;Subnode1 Id="C" /&gt; &lt;/Wigit&gt; &lt;Wigit&gt; &lt;EditStamp UserId="biff" Timestamp="2013-10-13T21:51:00" /&gt; &lt;Subnode1 Id="C" /&gt; &lt;/Wigit&gt; &lt;/Root&gt; </code></pre> <p>Any hints on how to not duplicate the results?</p> <p><strong>Update 10-16-2013:</strong></p> <p>The reason I was getting duplicate results is because the Updates doc I was using had two nodes. The code needs to handle multiple changes at once, updating only the nodes with a greater timestamp.</p> <pre><code>string update = @"&lt;?xml version='1.0' encoding='utf-8'?&gt; &lt;Root&gt; &lt;Wigit id='A'&gt; &lt;EditStamp UserId='frank' Timestamp='2013-10-13T22:00:00' /&gt; &lt;Subnode1 Id='SomeNewThing' /&gt; &lt;/Wigit&gt; &lt;Wigit id='B'&gt; &lt;EditStamp UserId='yomamma' Timestamp='2013-09-10T21:51:00' /&gt; &lt;Subnode1 Id='B' /&gt; &lt;/Wigit&gt; &lt;/Root&gt;"; </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload