クラス構造を次のようにする
[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; }
}
デシリアライズを使用してこれらのxmlをオブジェクトに変換し、再帰メソッドを呼び出して各ノードを比較し、最初の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;
}