比较两个xml并使用LINQ打印差异

我正在比较两个xml,我必须打印差异。 如何使用LINQ实现此目的。 我知道我可以使用Microsoft的XML diff补丁,但我更喜欢使用LINQ。 如果您有任何其他想法,我会实现它

//第一个Xml

              

//第二个Xml

               

我想比较这两个xml和打印结果。

 Issued Issue Type IssueInFirst IssueInSecond 1 image is different C01 C011 2 name is different ASP.NET ASP.NET 2.0 3 id is different 20507 20508 

这是解决方案:

 //sanitised xmls: string s1 = @"     "; string s2 = @"     "; XDocument xml1 = XDocument.Parse(s1); XDocument xml2 = XDocument.Parse(s2); //get cartesian product (i think) var result1 = from xmlBooks1 in xml1.Descendants("book") from xmlBooks2 in xml2.Descendants("book") select new { book1 = new { id=xmlBooks1.Attribute("id").Value, image=xmlBooks1.Attribute("image").Value, name=xmlBooks1.Attribute("name").Value }, book2 = new { id=xmlBooks2.Attribute("id").Value, image=xmlBooks2.Attribute("image").Value, name=xmlBooks2.Attribute("name").Value } }; //get every record that has at least one attribute the same, but not all var result2 = from i in result1 where (i.book1.id == i.book2.id || i.book1.image == i.book2.image || i.book1.name == i.book2.name) && !(i.book1.id == i.book2.id && i.book1.image == i.book2.image && i.book1.name == i.book2.name) select i; foreach (var aa in result2) { //you do the output :D } 

这两个linq语句可能都可以合并,但我将其作为练习留给你。

你想要的操作是一个Zip,用于配对你的两本书中的相应元素。 该操作符是在.NET 4.0中添加的 ,但是我们可以通过使用Select来获取书籍索引并加入其中来伪造它:

 var res = from b1 in xml1.Descendants("book") .Select((b, i) => new { b, i }) join b2 in xml2.Descendants("book") .Select((b, i) => new { b, i }) on b1.i equals b2.i 

然后,我们将使用第二个连接按名称比较属性的值。 请注意,这是一个内连接; 如果你确实想要包含一个或另一个缺少的属性,你将不得不做更多的工作。

  select new { Row = b1.i, Diff = from a1 in b1.b.Attributes() join a2 in b2.b.Attributes() on a1.Name equals a2.Name where a1.Value != a2.Value select new { Name = a1.Name, Value1 = a1.Value, Value2 = a2.Value } }; 

结果将是嵌套集合:

 foreach (var b in res) { Console.WriteLine("Row {0}: ", b.Row); foreach (var d in b.Diff) Console.WriteLine(d); } 

或者每本书获得多行:

 var report = from r in res from d in r.Diff select new { r.Row, Diff = d }; foreach (var d in report) Console.WriteLine(d); 

报告如下:

 { Row = 0, Diff = { Name = image, Value1 = C01, Value2 = C011 } } { Row = 1, Diff = { Name = name, Value1 = ASP.NET, Value2 = ASP.NET 2.0 } } { Row = 3, Diff = { Name = id, Value1 = 20507, Value2 = 20508 } } 

为了好玩,grega g阅读问题的一般解决方案。 为了说明我对这种方法的反对意见,我为’PowerShell in Action’引入了一个“正确”的条目。

 string s1 = @"      "; string s2 = @"      "; XDocument xml1 = XDocument.Parse(s1); XDocument xml2 = XDocument.Parse(s2); var res = from b1 in xml1.Descendants("book") from b2 in xml2.Descendants("book") let issues = from a1 in b1.Attributes() join a2 in b2.Attributes() on a1.Name equals a2.Name select new { Name = a1.Name, Value1 = a1.Value, Value2 = a2.Value } where issues.Any(i => i.Value1 == i.Value2) from issue in issues where issue.Value1 != issue.Value2 select issue; 

报告如下:

 { Name = image, Value1 = C01, Value2 = C011 } { Name = name, Value1 = ASP.NET, Value2 = ASP.NET 2.0 } { Name = id, Value1 = 20507, Value2 = 20508 } { Name = image, Value1 = C05, Value2 = C04 } { Name = name, Value1 = PowerShell in Action, Value2 = Architecting Applications } 

请注意,最后两个条目是20508拼写错误与其他正确的20508条目之间的“冲突”。