简体   繁体   中英

Compare XML for Differences

I am writing some C# code with the intention of periodically downloading an XML file, comparing the resulting XML with a previously downloaded version of XML (to detect changes), and then "actioning" the changes (via appropriate CRUD statements) by updating database records which reflect the entities in the XML.

I need some help with the "comparing the resulting XML with a previously downloaded version to detect changes " part of the requirements.

So... considering the following two XML documents which have minor differences...

Original

<ROOT>
   <Stock>
      <Vehicle id="2574074">
         <DealerName>Super Cars London</DealerName>
         <FriendlyName>Ford Ranger 3.2 double cab 4x4 XLT auto</FriendlyName>
         <ModelName>Ranger</ModelName>
         <MakeName>Ford</MakeName>
         <Registration>DG55TPG</Registration>
         <Price>40990</Price>
         <Colour>WHITE</Colour>
         <Year>2014</Year>
         <Mileage>52000</Mileage>
         <Images>
            <Image Id="4771304" ThumbUrl="http://www.somewhere.com/GetImage.aspx?ImageId=4771304&amp;Type=6&amp;Width=60&amp;Height=60&amp;FeedId=42" FullUrl="http://www.somewhere.com/GetImage.aspx?ImageId=4771304&amp;Type=6&amp;Width=640&amp;FeedId=42" LastModified="2016-02-02T08:24:51.48" Priority="1"/>
         </Images>
      </Vehicle>
      <Vehicle id="2648665">
         <DealerName>Super Cars London</DealerName>
         <FriendlyName>BMW 320i</FriendlyName>
         <ModelName>3 Series</ModelName>
         <MakeName>BMW</MakeName>
         <Registration>CN03YZG</Registration>
         <Price>24990</Price>
         <Colour>WHITE</Colour>
         <Year>2013</Year>
         <Mileage>96000</Mileage>
         <Images/>
      </Vehicle>
   </Stock>
</ROOT>

New

<ROOT>
   <Stock>
      <Vehicle id="2575124">
         <DealerName>Supercars London</DealerName>
         <FriendlyName>Ford Ranger 3.2 double cab 4x4 XLT auto</FriendlyName>
         <ModelName>Ranger</ModelName>
         <MakeName>Ford</MakeName>
         <Registration>DK08FKP</Registration>
         <Price>43990</Price>
         <Colour>WHITE</Colour>
         <Year>2014</Year>
         <Mileage>30000</Mileage>
         <Images>
            <Image Id="5119812" ThumbUrl="http://www.somewhere.com/GetImage.aspx?ImageId=5119812&amp;Type=6&amp;Width=60&amp;Height=60&amp;FeedId=42" FullUrl="http://www.somewhere.com/GetImage.aspx?ImageId=5119812&amp;Type=6&amp;Width=640&amp;FeedId=42" LastModified="2016-04-11T13:08:42.81" Priority="1"/>
         </Images>
      </Vehicle>
      <Vehicle id="2648665">
         <DealerName>Super Cars London</DealerName>
         <FriendlyName>BMW 320i</FriendlyName>
         <ModelName>3 Series</ModelName>
         <MakeName>BMW</MakeName>
         <Registration>CN03YZG</Registration>
         <Price>24990</Price>
         <Colour>BRILLIANT WHITE</Colour>
         <Year>2013</Year>
         <Mileage>96000</Mileage>
         <Images>
            <Image Id="5201856" ThumbUrl="http://www.somewhere.com/GetImage.aspx?ImageId=5201856&amp;Type=6&amp;Width=60&amp;Height=60&amp;FeedId=42" FullUrl="http://www.somewhere.com/GetImage.aspx?ImageId=5201856&amp;Type=6&amp;Width=640&amp;FeedId=42" LastModified="2016-04-25T12:12:05.827" Priority="1"/>
            <Image Id="5201857" ThumbUrl="http://www.somewhere.com/GetImage.aspx?ImageId=5201857&amp;Type=6&amp;Width=60&amp;Height=60&amp;FeedId=42" FullUrl="http://www.somewhere.com/GetImage.aspx?ImageId=5201857&amp;Type=6&amp;Width=640&amp;FeedId=42" LastModified="2016-04-25T12:12:09.117" Priority="2"/>
            <Image Id="5201858" ThumbUrl="http://www.somewhere.com/GetImage.aspx?ImageId=5201858&amp;Type=6&amp;Width=60&amp;Height=60&amp;FeedId=42" FullUrl="http://www.somewhere.com/GetImage.aspx?ImageId=5201858&amp;Type=6&amp;Width=640&amp;FeedId=42" LastModified="2016-04-25T12:12:13.59" Priority="3"/>
            <Image Id="5201859" ThumbUrl="http://www.somewhere.com/GetImage.aspx?ImageId=5201859&amp;Type=6&amp;Width=60&amp;Height=60&amp;FeedId=42" FullUrl="http://www.somewhere.com/GetImage.aspx?ImageId=5201859&amp;Type=6&amp;Width=640&amp;FeedId=42" LastModified="2016-04-25T12:12:18.453" Priority="4"/>
            <Image Id="5201860" ThumbUrl="http://www.somewhere.com/GetImage.aspx?ImageId=5201860&amp;Type=6&amp;Width=60&amp;Height=60&amp;FeedId=42" FullUrl="http://www.somewhere.com/GetImage.aspx?ImageId=5201860&amp;Type=6&amp;Width=640&amp;FeedId=42" LastModified="2016-04-25T12:12:22.853" Priority="5"/>
         </Images>
      </Vehicle>
   </Stock>
</ROOT>

Summary of Differences

  1. Vehicle id="2575124" is not present in the original. This represents a "create".
  2. Vehicle id="2574074" is not present in the new. This represents a "delete".
  3. Vehicle id="2648665" (which is present in both original and new) has a different <Colour> (WHITE -> BRILLIANT WHITE). This represents an "update".
  4. Vehicle id="2648665" also has new <Image> nodes in the new. This represents a "create" (as images will be 1:M with the vehicle in the database).

I have looked at XMLDiff to generate a DiffGram with add/change/remove instructions but I can't see a way to make it generate a DiffGram that represent the changes I've summarised, eg it sees changes 1 and 2 as an "change" - <xd:change match="@id">2648665</xd:change> - rather than the absence and addition of a vehicle.

Is there a way to do this with XMLDiff?

Or, is there a "better" way to achieve the result I'm looking for?

I've found that LINQ can do a pretty good job of parsing the XML for differences, eg..

XDocument xNewVehicle = new XDocument(new XElement("UsedStock",
                    from newVehicle in newXml.Descendants("Vehicle")
                    join oldVehicle in oldXml.Descendants("Vehicle")
                        on newVehicle.Attributes("id").First().Value equals oldVehicle.Attributes("id").First().Value into oldVehicles
                    where !oldVehicles.Any()  // where the vehicle exists in new but not in old
                        || newVehicle.ToString() != oldVehicles.First().ToString()  // where the new vehicle is not the same as the old vehicle
                select newVehicle));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM