简体   繁体   中英

C#: Diff of two XML files - get only the nodes that have been modified/updated

I would like to get a list of nodes which have been modified (nodes added and nodes updated).

This is my program and XML files (before and after update)

fileBeforeUpdate.xml

<?xml version="1.0"?>
<DESCRIPTION>
    <DISTRIBUE_PAR>
      <UID>0000000000001</UID>
      <NOM>Anthony</NOM>
    </DISTRIBUE_PAR>
    <OBJET>Object Node</OBJET>
    <SUPPORT HREF="#PAPER"/>
    <NUMEROS_CHRONO>
      <CHRONO_1>aqwzsxedc-123456</CHRONO_1>
    </NUMEROS_CHRONO>
    <REFERENCE>reference</REFERENCE>
</DESCRIPTION>

fileAfterUpdate.xml

<?xml version="1.0"?>
<DESCRIPTION>
    <DISTRIBUE_PAR>
      <NOM>Antoni</NOM>
    </DISTRIBUE_PAR>
    <OBJET>Object Node</OBJET>
    <SUPPORT HREF="#MAIL"/>
    <NUMEROS_CHRONO>
      <CHRONO_1>aqwzsxedc-123456</CHRONO_1>
    </NUMEROS_CHRONO>
    <REFERENCE>reference</REFERENCE>
    <DATE>01/03/1994</DATE>
</DESCRIPTION>

Program.cs

var sb = new StringBuilder();
using (XmlWriter xmlWriter = XmlWriter.Create(sb))
{
    XmlDiff diff = new XmlDiff(XmlDiffOptions.IgnoreComments | XmlDiffOptions.IgnoreWhitespace | XmlDiffOptions.IgnoreNamespaces);
    diff.Compare(@"C:\fileBeforeUpdate", @"C:\fileAfterUpdate", true, xmlWriter);
    diff.Algorithm = XmlDiffAlgorithm.Precise;

    XmlDocument doc = new XmlDocument();
    doc.LoadXml(sb.ToString());
 }

This is the StringBuilder output:

<xd:node match=\"1\">
    <xd:node match=\"1\">
        <xd:remove match=\"1\" />
        <xd:node match=\"2\">
            <xd:change match=\"1\">Antoni</xd:change>
        </xd:node>
    </xd:node>
    <xd:node match=\"3\">
        <xd:change match=\"@HREF\">#MAIL</xd:change>
    </xd:node>
    <xd:node match=\"5\" />
    <xd:add>
        <DATE>01/03/1994</DATE>
    </xd:add>
</xd:node>

For getting the list of nodes added, it's easily (in StringBuilder , I have node <xd:add> with node which added and values).

var addNodes = doc.GetElementsByTagName("xd:add");
var xmlNodesAdded = new StringBuilder();

foreach (XmlNode node in addNodes)
{
       xmlNodesAdded.Append(node.InnerXml);
       xmlNodesAdded.AppendLine();
}

However, to get the list of nodes (and attributes) which have been modified, it's more difficult...

How can I achieve this?
In StringBuilder , nodes xd:change do not specify the node which have been updated...

Thank you in advance.

You can get HTML presentation of the changes by using XmlDiffView. (In some cases it wont recognize the change type correctly).

public string GetChangeHtml(string originalXML, string changedXML)
{
    XmlDiffView view = new XmlDiffView();
    var diffgram = Diff(originalXML, changedXML);
    string ret = "";
    using (StringReader legacySr = new StringReader(originalXML), diffGramSr = new StringReader(diffgram.ToString()))
    {
        using (XmlReader legacyReader = XmlReader.Create(legacySr), diffgramReader = XmlReader.Create(diffGramSr))
        {
            using (StringWriter sw = new StringWriter())
            {
                view.Load(legacyReader, diffgramReader);
                view.GetHtml(sw);
                ret = sw.ToString();
            }
        }
    }
    return ret;
}

Check the code in my question below: XMLDiff fails to recognize differences correcly?

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