public void HighlightAttributes() { // NOTE (steveb): test unamibiguous addition, deletion, and replacement XDoc a = XDocFactory.From("<p>the <span class=\"red\">brown</span> fox</p>", MimeType.XML); XDoc b = XDocFactory.From("<p>the <span class=\"blue\">brown</span> fox</p>", MimeType.XML); var diff = XDocDiff.Diff(a, b, 10000); List <Tuple <string, string, string> > invisible; XDoc doc; XDoc before; XDoc after; XDocDiff.Highlight(diff, out doc, out invisible, out before, out after); Assert.AreEqual("<p>the <span class=\"blue\">brown</span> fox</p>", doc.ToString()); Assert.AreEqual(1, invisible.Count); Assert.AreEqual(invisible[0].Item1, "/p/span/@class"); Assert.AreEqual(invisible[0].Item2, "red"); Assert.AreEqual(invisible[0].Item3, "blue"); Assert.AreEqual(a.ToString(), before.ToString()); Assert.AreEqual(b.ToString(), after.ToString()); }
internal static XDoc GetPageDiff(XDoc before, XDoc after, bool compact, int maxDelta, out XDoc invisibleDiff, out DekiResource summary, out XDoc beforeHighlightedChanges, out XDoc afterHighlightedChanges) { var resources = DekiContext.Current.Resources; XDoc result = XDoc.Empty; beforeHighlightedChanges = before; afterHighlightedChanges = after; invisibleDiff = XDoc.Empty; // compute diff between the two documents Tuplet <ArrayDiffKind, XDocDiff.Token>[] diff = XDocDiff.Diff(before, after, maxDelta); if (diff == null) { summary = DekiResources.PAGE_DIFF_TOO_LARGE(); return(result); } // create change summary int added; int removed; int attributes; int structural; summary = GetChangeSummary(diff, out added, out removed, out attributes, out structural); // create document with highlighted changes if ((added > 0) || (removed > 0) || (attributes > 0)) { try { List <Tuplet <string, string, string> > invisibleChanges; XDocDiff.Highlight(diff, out result, out invisibleChanges, out beforeHighlightedChanges, out afterHighlightedChanges); // check if we should only keep top-level elements that contain changes to cut down on the noise if (compact) { if ((added > 0) || (removed > 0)) { CompactDiff(result); CompactDiff(beforeHighlightedChanges); CompactDiff(afterHighlightedChanges); } else { // no changes were made, remove all nodes result = XDoc.Empty; } } // add invisible changes if (invisibleChanges.Count > 0) { invisibleDiff = new XDoc("ol"); foreach (Tuplet <string, string, string> change in invisibleChanges) { invisibleDiff.Start("li"); invisibleDiff.Value(string.Format("{0}: ", change.Item1)); if (change.Item2 != null) { invisibleDiff.Elem("del", change.Item2.QuoteString()); } else { invisibleDiff.Value(resources.Localize(DekiResources.PAGE_DIFF_NOTHING())); } invisibleDiff.Value(" " + DOUBLE_ARROW + " "); if (change.Item3 != null) { invisibleDiff.Elem("ins", change.Item3.QuoteString()); } else { invisibleDiff.Value(resources.Localize(DekiResources.PAGE_DIFF_NOTHING())); } invisibleDiff.End(); } } } catch (Exception e) { summary = DekiResources.PAGE_DIFF_ERROR("MindTouch", e); } } return(result); }