如何同步两个xml文件?

时间:2013-04-24 09:47:44

标签: xml merge sync

我在服务器中有XML1,如下所示

  <?xml version="1.0" encoding="utf-8"?>
<Node id="0" Value="Root">
<Node id="1" Value="L1">
<Node id="1.1" Value="N11">
  <Node id="1.1.2" Value="N112" />
 </Node>
</Node>
<Node id="2" Value="L2">
<Node id="2.1" Value="N21" />
 </Node>
</Node>

我在本地有另一个XML2,如下所示

<?xml version="1.0" encoding="utf-8"?>
<Node id="0" Value="Root">
 <Node id="1" Value="L1">
<Node id="1.1" Value="N11"></Node>
<Node id="1.2" Value="N12"></Node>
 </Node>
<Node id="2.1" Value="N21"></Node>
</Node>

现在我想同步这两个xml并输出如下所示

<?xml version="1.0" encoding="utf-8"?>
<Node id="0" Value="Root">
 <Node id="1" Value="L1">
<Node id="1.1" Value="N11" />
<Node id="1.2" Value="N12" />
  </Node>
  <Node id="2.1" Value="N21" />
</Node>

请提供解决方案..提前感谢

1 个答案:

答案 0 :(得分:2)

使类结构像

 [XmlTypeAttribute(AnonymousType = true)]
public class Node
{
    [XmlAttribute(AttributeName = "id")]
    public string Id { get; set; }

    [XmlAttribute(AttributeName = "Value")]
    public string Name { get; set; }

    [XmlAttribute(AttributeName = "Status")]
    public string Status { get; set; }

    [XmlElement("Node")]
    public List<Node> Nodes { get; set; }
}

通过使用反序列化将这些xmls转换为对象并调用递归方法来比较每个节点并合并到第一个xml中。

private void sync_Click(object sender, EventArgs e)
    {
        strLogg = string.Empty;
        Node oSource = FillData(textBox1.Text + ".xml");
        Node oDesignation = FillData(textBox2.Text + ".xml");
        UpdateNodes(oSource, oDesignation);
        WriteXML(oSource,"XML1.xml");
        string strHeader = "Changes at " + DateTime.Now + System.Environment.NewLine;
        System.IO.File.AppendAllText(exportPath + "xmlLogger.txt",  strHeader + strLogg + Environment.NewLine);
        //System.Diagnostics.Process.Start(exportPath + "\\xmlLogger.txt"); // show log file

    }


 private static Node FillData(string xmlName)
    {
        string path = exportPath + xmlName;
        FileStream fs = new FileStream(path, FileMode.Open);
        XmlReader reader = new XmlTextReader(fs);
        XmlRootAttribute xRoot = new XmlRootAttribute("Node");
        xRoot.IsNullable = true;
        var serializer = new XmlSerializer(typeof(Node), xRoot);
        var result = (Node)serializer.Deserialize(reader);
        reader.Close();

        return result;
    }


private void UpdateNodes(Node n1, Node n2)
    {
        // Update Value
        if (n1.Name != n2.Name)
        {
            LogChanges(n1.Name + " Changed as " + n2.Name);
        }

        n1.Name = n2.Name;
        if (n1.Nodes != null || n2.Nodes != null)
        {

            if ((n1.Nodes != null && n1.Nodes.Count > 0) && (n2.Nodes != null && n2.Nodes.Count > 0))
            {
                // add new nodes to XML1
                var newNodes = n2.Nodes.Where(ns => (!(n1.Nodes.Select(nn => nn.Id).ToList()).Contains(ns.Id) && ns.Status != "del")).ToList();
                newNodes.ForEach(n => LogChanges("Added " + n.Name));
                n1.Nodes.AddRange(newNodes);

                // delete nodes from XML1
                var delNodes = n2.Nodes.Where(ns => ((n1.Nodes.Select(nn => nn.Id).ToList()).Contains(ns.Id) && ns.Status == "del")).ToList();
                if (delNodes.Count > 0)
                {
                    delNodes.ForEach(n => LogChanges("Deleted " + n.Name));
                }
                n1.Nodes.RemoveAll(ns => n2.Nodes.Count(nn => nn.Id == ns.Id && nn.Status == "del") > 0);


                if (n2.Nodes.Count > 0 && n2.Nodes.Count > 0)
                {
                    n1.Nodes.ToList().ForEach(n =>
                    {
                        if (n2.Nodes.Count(ns2 => ns2.Id == n.Id) > 0)
                        {
                            UpdateNodes(n, n2.Nodes.Where(ns2 => ns2.Id == n.Id).FirstOrDefault());
                        }
                    }
                        );
                }
            }
            else if ((n1.Nodes != null && n1.Nodes.Count > 0) && (n2.Nodes == null || n2.Nodes.Count == 0))
            {
                n2.Nodes = new List<Node>();
                n2.Nodes.AddRange(n1.Nodes);
            }
            else if ((n1.Nodes == null || n1.Nodes.Count == 0) && (n2.Nodes != null && n2.Nodes.Count > 0 && n2.Nodes.Count(ns => ns.Status !="del") > 0))
            {
                n1.Nodes = new List<Node>();
                n1.Nodes.AddRange(n2.Nodes);
                n2.Nodes.ForEach(n => LogChanges("Added  " + n.Name));
            }
        }
    }


    private void LogChanges(string sName)
    {
        strLogg +=  sName +  System.Environment.NewLine;
    }