private static void TwoWayDiff(XElement baseElem, XElement compareElem, ElementWriter bWriter, ElementWriter cWriter, List<ListCompare> results) { var baseList = GetKeys(baseElem.Elements()); var compareList = GetKeys(compareElem.Elements()); var compares = ListCompare.Create(baseList, compareList, v => v.Item1); // Deal with the relationships of versionable items if (baseElem.Name.LocalName == "Relationships" && !compares.Any(c => c.Base >= 0 && c.Compare >= 0)) { var baseRelateds = baseElem.Elements().Select(e => Tuple.Create(GetRelatedId(e), e)).ToList(); var compareRelateds = compareElem.Elements().Select(e => Tuple.Create(GetRelatedId(e), e)).ToList(); if (!baseRelateds.Any(t => string.IsNullOrEmpty(t.Item1)) && !compareRelateds.Any(t => string.IsNullOrEmpty(t.Item1)) && baseRelateds.Select(t => t.Item1).Distinct().Count() == baseRelateds.Count && compareRelateds.Select(t => t.Item1).Distinct().Count() == compareRelateds.Count) { compares = ListCompare.Create(baseRelateds, compareRelateds, v => v.Item1); } } int start; foreach (var tuple in compares) { if (tuple.Base < 0) { start = cWriter.CurrentLine + 1; cWriter.WriteElement(compareList[tuple.Compare].Item2); results.AddRange(Enumerable.Range(start, cWriter.CurrentLine - start + 1).Select(i => new ListCompare(-1, i))); } else if (tuple.Compare < 0) { start = bWriter.CurrentLine + 1; bWriter.WriteElement(baseList[tuple.Base].Item2); results.AddRange(Enumerable.Range(start, bWriter.CurrentLine - start + 1).Select(i => new ListCompare(i, -1))); } else if (baseList[tuple.Base].Item2.Elements().Any() && compareList[tuple.Compare].Item2.Elements().Any()) { results.Add(new ListCompare(bWriter.CurrentLine + 1, cWriter.CurrentLine + 1) { IsDifferent = false }); bWriter.WriteStartElement(baseList[tuple.Base].Item2); cWriter.WriteStartElement(compareList[tuple.Compare].Item2); TwoWayDiff(baseList[tuple.Base].Item2, compareList[tuple.Compare].Item2, bWriter, cWriter, results); bWriter.WriteEndElement(); cWriter.WriteEndElement(); } else if (baseList[tuple.Base].Item2.Elements().Any() || compareList[tuple.Compare].Item2.Elements().Any() || baseList[tuple.Base].Item2.Value != compareList[tuple.Compare].Item2.Value) { results.Add(new ListCompare(bWriter.CurrentLine + 1, cWriter.CurrentLine + 1) { IsDifferent = true }); for (int i = results.Last().Base; i < bWriter.CurrentLine; i++) results.Add(new ListCompare(i, -1)); for (int i = results.Last().Compare; i < cWriter.CurrentLine; i++) results.Add(new ListCompare(-1, i)); bWriter.WriteElement(baseList[tuple.Base].Item2); cWriter.WriteElement(compareList[tuple.Compare].Item2); } else { results.Add(new ListCompare(bWriter.CurrentLine + 1, cWriter.CurrentLine + 1)); bWriter.WriteElement(baseList[tuple.Base].Item2); cWriter.WriteElement(compareList[tuple.Compare].Item2); } } }