private void Form1_Load(object sender, System.EventArgs e)
        {
            var d             = new Differ();
            var inlineBuilder = new SideBySideDiffBuilder(d);
            var diffmodel     = inlineBuilder.BuildDiffModel(OldText, NewText);

            webBrowser1.DocumentText = GetHtml2Render(diffmodel.OldText);
            webBrowser2.DocumentText = GetHtml2Render(diffmodel.NewText);

            webBrowser1.Refresh();
            webBrowser2.Refresh();
        }
Example #2
0
            public void Will_throw_is_OldText_is_null()
            {
                var differ  = new Mock <IDiffer>();
                var builder = new SideBySideDiffBuilder(differ.Object);

                var ex = Record.Exception(() => builder.BuildDiffModel(null, "asd"));

                Assert.IsType <ArgumentNullException>(ex);
                var an = (ArgumentNullException)ex;

                Assert.Equal("oldText", an.ParamName);
            }
Example #3
0
        public List <string> GetDiffer(string OldText, string NewText)
        {
            List <string> Diff          = new List <string>();
            var           inlineBuilder = new SideBySideDiffBuilder(new Differ());

            var diffmodel = inlineBuilder.BuildDiffModel(OldText, NewText);

            Diff.Add(Differ(diffmodel.OldText));
            Diff.Add(Differ(diffmodel.NewText));

            return(Diff);
        }
            public void Will_not_ignore_word_white_space()
            {
                string oldText = "My name is matt";
                string newText = "My name is   matt";
                var    sideBySideDiffBuilder = new SideBySideDiffBuilder();
                var    sideBySideDiffModel   = sideBySideDiffBuilder.BuildDiffModel(oldText, newText, false);

                Assert.NotNull(sideBySideDiffModel);
                Assert.Single(sideBySideDiffModel.OldText.Lines);
                Assert.Single(sideBySideDiffModel.NewText.Lines);
                Assert.True(sideBySideDiffModel.OldText.HasDifferences);
                Assert.True(sideBySideDiffModel.NewText.HasDifferences);
            }
        private void ShowDiffs(string oldText, string newText)
        {
            IDiffer differ = new Differ();

            DiffResult diffResult = differ.CreateLineDiffs(oldText, newText, false);

            ISideBySideDiffBuilder diffBuilder = new SideBySideDiffBuilder(differ);

            SideBySideDiffModel model = diffBuilder.BuildDiffModel(oldText, newText);

            this.DisplayDiffPiece(this.rtbSnapshotLeft, model.OldText.Lines, string.IsNullOrEmpty(newText));
            this.DisplayDiffPiece(this.rtbSnapshotRight, model.NewText.Lines, false);
        }
Example #6
0
        internal static string[] DoSideBySideDiff(string SourceText, string DestinationText)
        {
            string[] Result    = new string[3];
            Differ   DiffMaker = new Differ();
            SideBySideDiffBuilder SideBySideDiffer     = new SideBySideDiffBuilder(DiffMaker);
            SideBySideDiffModel   SideBySideDiffResult = SideBySideDiffer.BuildDiffModel(SourceText, DestinationText);
            int DiffLevel = IronDiffer.GetLevel(SideBySideDiffResult, SourceText, DestinationText);

            Result[0] = FullDiff(SideBySideDiffResult.OldText.Lines);
            Result[1] = FullDiff(SideBySideDiffResult.NewText.Lines);
            Result[2] = DiffLevel.ToString();
            return(Result);
        }
Example #7
0
        public SideBySideDiff CompareString(string generatedFile, string referenceFile, string filenameA, string filenameB)
        {
            var generated = generatedFile.TrimEnd();
            var reference = referenceFile.TrimEnd();

            var diffBuilder = new SideBySideDiffBuilder(new Differ());
            var diff        = diffBuilder.BuildDiffModel(generated, reference, true);

            return(new SideBySideDiff
            {
                A = filenameA,
                B = filenameB,
                Diff = diff
            });
        }
Example #8
0
        private void ShowChanges(int leftIndex, int rightIndex)
        {
            if (InvokeRequired)
            {
                Invoke(new Action <int, int>(ShowChanges), leftIndex, rightIndex);
                return;
            }
            var left    = leftIndex == -1 ? string.Empty : revisionProvider.Revisions[leftIndex].GetContent();
            var right   = revisionProvider.Revisions[rightIndex].GetContent();
            var builder = new SideBySideDiffBuilder(new Differ());
            var model   = builder.BuildDiffModel(left, right);

            ChangeStartPositions = ModelToTextBox(model.OldText, rtbLeft, rtbLeftNumbers);
            ModelToTextBox(model.NewText, rtbRight, rtbRightNumbers);
            lblChanges.Text = ChangeStartPositions.Count + " change" + (ChangeStartPositions.Count == 1 ? string.Empty : "s");
        }
Example #9
0
        private static void InitializeChildRows(CremaDataRow diffRow1, CremaDataRow diffRow2, CremaDataRow dataRow1, CremaDataRow dataRow2, CremaDataTable diffChildTable1, CremaDataTable diffChildTable2, CremaDataTable childTable1, CremaDataTable childTable2)
        {
            var emptyRows     = new CremaDataRow[] { };
            var inlineBuilder = new SideBySideDiffBuilder(new Differ());

            var childRows1 = dataRow1 != null && childTable1 != null?dataRow1.GetChildRows(childTable1) : emptyRows;

            var childRows2 = dataRow2 != null && childTable2 != null?dataRow2.GetChildRows(childTable2) : emptyRows;

            var rowText1 = GetString(childRows1);
            var rowText2 = GetString(childRows2);
            var rowDiff  = inlineBuilder.BuildDiffModel(rowText1, rowText2);

            FillChildRow(diffRow1, dataRow1, diffChildTable1, childTable1, childRows1, rowDiff.OldText.Lines);
            FillChildRow(diffRow2, dataRow2, diffChildTable2, childTable2, childRows2, rowDiff.NewText.Lines);
        }
            public void Will_pass_correct_word_separators_to_constructor_to_create_word_diff()
            {
                string text = "a\nb\nc\nd\n\n";

                string[] textLines = { "a", "b", "c", "d", "" };
                char[]   chars     = { ' ', '.' };
                var      builder   = new SideBySideDiffBuilder(new Differ(), chars);

                builder.BuildDiffModel(text, text);

                Assert.Equal(builder.WordSeparaters.Length, chars.Length);
                foreach (var c in builder.WordSeparaters)
                {
                    Assert.Contains(c, chars);
                }
            }
        private void compareTreeViewStrings(MyTreeView newTreeView, string newText, MyTreeView oldTreeView, string oldText)
        {
            ISideBySideDiffBuilder diffBuilder     = new SideBySideDiffBuilder(new Differ());
            SideBySideDiffModel    sideBySideModel = diffBuilder.BuildDiffModel(oldText, newText);

            newTreeView.Nodes.Clear();
            oldTreeView.Nodes.Clear();

            TreeNode newParentNode = newTreeView.Nodes.Add(sideBySideModel.NewText.Lines[0].Text);
            TreeNode oldParentNode = oldTreeView.Nodes.Add(sideBySideModel.OldText.Lines[0].Text);

            colorTreeView(newParentNode.FullPath, newParentNode, sideBySideModel.NewText.Lines, sideBySideModel.OldText.Lines, 1, true);
            colorTreeView(oldParentNode.FullPath, oldParentNode, sideBySideModel.OldText.Lines, sideBySideModel.NewText.Lines, 1, false);

            newTreeView.AddLinkedTreeView(oldTreeView);
        }
Example #12
0
        public void ThenCompareWithDiffPlexTheFollowngFilesVs(string fileOne, string fileTwo)
        {
            string str1 = FileStorage.ReadFileText(fileOne.StrVar());
            string str2 = FileStorage.ReadFileText(fileTwo.StrVar());

            var d1         = new Differ();
            var sidebYSide = new SideBySideDiffBuilder(d1);
            var result1    = sidebYSide.BuildDiffModel(str1, str2);

            foreach (var line in result1.NewText.Lines)
            {
                if (line.Type == ChangeType.Modified)
                {
                    Assert.Fail(line.Position + " " + line.Text);
                }
            }
        }
Example #13
0
        public void Report(string approved, string received)
        {
            var approvedText = File.ReadAllText(approved);
            var receivedText = File.ReadAllText(received);

            var diffBuilder = new SideBySideDiffBuilder(new Differ());
            var diff        = diffBuilder.BuildDiffModel(approvedText, receivedText);

            var sb = new StringBuilder()
                     .AppendLine($"<<<<<<<<< {Path.GetFileName(approved)}")
                     .AppendDiff(diff.OldText)
                     .AppendLine("=========")
                     .AppendDiff(diff.NewText)
                     .Append($">>>>>>>>> {Path.GetFileName(received)}");

            //_out.WriteLine(sb.ToString());
            throw new ApiNotApprovedException(sb.ToString());
        }
Example #14
0
        public ActionResult Index(int id, List <int> grSel)
        {
            var db   = new ZkDataContext();
            var post = db.ForumPosts.Find(id);

            string txt1 = "";
            string txt2 = "";

            if (grSel != null && grSel.Any())
            {
                if (grSel.Count > 1)
                {
                    txt1 = db.ForumPostEdits.Find(grSel.Min())?.NewText;
                    txt2 = db.ForumPostEdits.Find(grSel.Max())?.NewText;
                }
                else
                {
                    var edit = db.ForumPostEdits.Find(grSel.First());
                    if (edit != null)
                    {
                        txt1 = edit.OriginalText;
                        txt2 = edit.NewText;
                    }
                }

                var sd = new SideBySideDiffBuilder(new Differ());
                ViewBag.DiffModel = sd.BuildDiffModel(txt1, txt2);
            }
            else
            {
                var edit = post.ForumPostEdits.OrderByDescending(x => x.ForumPostEditID).FirstOrDefault();
                if (edit != null)
                {
                    var sd = new SideBySideDiffBuilder(new Differ());
                    ViewBag.DiffModel = sd.BuildDiffModel(edit.OriginalText, edit.NewText);
                }
            }


            return(View("PostHistoryIndex", post));
        }
            public void Will_build_diffModel_for_partially_different_lines()
            {
                string textOld = "m is h";
                string textNew = "m ai is n h";

                string[] textLinesOld = { "m is h" };
                string[] textLinesNew = { "m ai is n h" };
                var      differ       = new Mock <IDiffer>();

                differ.Setup(x => x.CreateDiffs(textOld, textNew, true, false, It.IsNotNull <IChunker>()))
                .Returns(new DiffResult(textLinesOld, textLinesNew, new List <DiffBlock> {
                    new DiffBlock(0, 1, 0, 1)
                }));
                differ.Setup(x => x.CreateDiffs(It.IsAny <string>(), It.IsAny <string>(), false, false, It.IsNotNull <IChunker>()))
                .Returns(new DiffResult(
                             new[] { "m ", "is ", "h" },
                             new[] { "m ", "ai ", "is ", "n ", "h" },
                             new List <DiffBlock> {
                    new DiffBlock(1, 0, 1, 1), new DiffBlock(3, 0, 3, 1)
                }));
                var builder = new SideBySideDiffBuilder(differ.Object);

                var bidiff = builder.BuildDiffModel(textOld, textNew);

                Assert.NotNull(bidiff);
                Assert.Single(bidiff.OldText.Lines);
                Assert.Single(bidiff.NewText.Lines);
                Assert.Equal(ChangeType.Unchanged, bidiff.NewText.Lines[0].SubPieces[0].Type);
                Assert.Equal(ChangeType.Inserted, bidiff.NewText.Lines[0].SubPieces[1].Type);
                Assert.Equal(ChangeType.Unchanged, bidiff.NewText.Lines[0].SubPieces[2].Type);
                Assert.Equal(ChangeType.Inserted, bidiff.NewText.Lines[0].SubPieces[3].Type);
                Assert.Equal(ChangeType.Unchanged, bidiff.NewText.Lines[0].SubPieces[4].Type);

                Assert.Equal(ChangeType.Unchanged, bidiff.OldText.Lines[0].SubPieces[0].Type);
                Assert.Equal(ChangeType.Imaginary, bidiff.OldText.Lines[0].SubPieces[1].Type);
                Assert.Equal(ChangeType.Unchanged, bidiff.OldText.Lines[0].SubPieces[2].Type);
                Assert.Equal(ChangeType.Imaginary, bidiff.OldText.Lines[0].SubPieces[3].Type);
                Assert.Equal(ChangeType.Unchanged, bidiff.OldText.Lines[0].SubPieces[4].Type);

                Assert.True(bidiff.OldText.HasDifferences && bidiff.NewText.HasDifferences);
            }
Example #16
0
        public virtual ActionResult Diff(string folderName, string parentFolder, string uuid, string version)
        {
            TextFolder textFolder = new TextFolder(Repository, folderName).AsActual();
            var        schema     = textFolder.GetSchema().AsActual();

            var versions    = version.Split(',');
            var v1          = int.Parse(versions[0]);
            var v2          = int.Parse(versions[1]);
            var textContent = schema.CreateQuery().WhereEquals("UUID", uuid).FirstOrDefault();


            var version1        = VersionManager.GetVersion(textContent, v1);
            var version1Content = new TextContent(version1.TextContent);
            var version2        = VersionManager.GetVersion(textContent, v2);
            var version2Content = new TextContent(version2.TextContent);


            var sideBySideDiffBuilder = new SideBySideDiffBuilder(new Differ());

            var model = new TextContentDiffModel()
            {
                UUID = uuid, Version1Name = v1, Version2Name = v2
            };


            foreach (var k in textContent.Keys)
            {
                var version1Text = version1Content[k] != null ? version1Content[k].ToString() : "";

                var version2Text = version2Content[k] != null ? version2Content[k].ToString() : "";

                var diffModel = sideBySideDiffBuilder.BuildDiffModel(version1Text, version2Text);

                model.Version1.Add(k, diffModel.OldText);
                model.Version2.Add(k, diffModel.NewText);
            }


            return(View(model));
        }
            public void Will_build_diffModel_when_oldText_is_empty()
            {
                string textOld = "";
                string textNew = "z\ny\nx\nw\n";

                string[] textLinesOld = {};
                string[] textLinesNew = { "z", "y" };
                var      differ       = new Mock <IDiffer>();

                differ.Setup(x => x.CreateDiffs(textOld, textNew, true, false, It.IsNotNull <IChunker>()))
                .Returns(new DiffResult(textLinesOld, textLinesNew, new List <DiffBlock> {
                    new DiffBlock(0, 0, 0, 2)
                }));
                differ.Setup(x => x.CreateDiffs(It.IsAny <string>(), It.IsAny <string>(), false, false, It.IsNotNull <IChunker>()))
                .Returns(new DiffResult(new string[0], new string[0], new List <DiffBlock>()));
                var builder = new SideBySideDiffBuilder(differ.Object);

                var bidiff = builder.BuildDiffModel(textOld, textNew);

                Assert.NotNull(bidiff);
                Assert.Equal(2, bidiff.OldText.Lines.Count);
                Assert.Equal(2, bidiff.NewText.Lines.Count);

                for (int j = 0; j < textLinesNew.Length; j++)
                {
                    Assert.Equal(textLinesNew[j], bidiff.NewText.Lines[j].Text);
                    Assert.Equal(ChangeType.Inserted, bidiff.NewText.Lines[j].Type);
                    Assert.Equal(j + 1, bidiff.NewText.Lines[j].Position);

                    Assert.Null(bidiff.OldText.Lines[j].Text);
                    Assert.Equal(ChangeType.Imaginary, bidiff.OldText.Lines[j].Type);
                    Assert.False(bidiff.OldText.Lines[j].Position.HasValue);
                }

                Assert.True(bidiff.OldText.HasDifferences && bidiff.NewText.HasDifferences);
            }
Example #18
0
        public static IEnumerable <FileDifferences> CompareFileContent(string oldFileContent, string newFileContent)
        {
            if (oldFileContent == null || newFileContent == null)
            {
                Trace.WriteLine("One of the file content is null");
                return(null);
            }

            if (oldFileContent == newFileContent)
            {
                Trace.WriteLine("Files are identical");
                return(null);
            }

            const string matchText = "<tr><th>Coverage:</th><td>0%</td></tr>";

            if (oldFileContent.Contains(matchText) && newFileContent.Contains(matchText))
            {
                Trace.WriteLine("Both files have no coverage.");
                return(null);
            }

            oldFileContent = RemoveLineNumbers(oldFileContent);
            newFileContent = RemoveLineNumbers(newFileContent);
            SideBySideDiffBuilder sideBySideDiffer = new SideBySideDiffBuilder(new Differ());
            SideBySideDiffModel   diff             = sideBySideDiffer.BuildDiffModel(oldFileContent, newFileContent);

            DiffPiece[] newLines = diff.NewText.Lines.Where(DoesLineHaveDifferentCoverage).ToArray();
            if (!diff.OldText.Lines.Where(DoesLineHaveDifferentCoverage).Concat(newLines).Any())
            {
                Trace.WriteLine("No changes to code coverage");
                return(null);
            }

            return(AnalyzeDiff(diff, newLines));
        }
        private void Row_DoubleClick(object sender, MouseButtonEventArgs e)
        {
            // execute some code
            DataGridRow      r  = (DataGridRow)sender;
            dynamic          i  = r.Item;
            FHXCompareResult rs = i.Value;

            var diffBuilder = new SideBySideDiffBuilder(new Differ());

            if (rs.NewValue == null)
            {
                this.tbOld.Document.Blocks.Clear();
                this.tbNew.Document.Blocks.Clear();

                var p  = new Paragraph();
                var tr = new TextRange(p.ContentStart, p.ContentEnd);
                tr.Text = rs.OldValue;

                this.tbOld.Document.Blocks.Add(p);
            }
            else
            {
                var diff = diffBuilder.BuildDiffModel(rs.OldValue, rs.NewValue);

                RichTextBox[] tb = new RichTextBox[2] {
                    this.tbOld, this.tbNew
                };
                List <DiffPiece>[] t = new List <DiffPiece>[2] {
                    diff.OldText.Lines, diff.NewText.Lines
                };

                for (int j = 0; j < 2; j++)
                {
                    tb[j].Document.Blocks.Clear();
                    foreach (DiffPiece line in t[j])
                    {
                        var p = new Paragraph();
                        p.Margin = new Thickness(0);
                        TextRange tr;
                        tr = new TextRange(p.ContentStart, p.ContentEnd);
                        switch (line.Type)
                        {
                        case ChangeType.Inserted:
                            tr.Text = line.Text;
                            tr.ApplyPropertyValue(TextElement.BackgroundProperty, Brushes.LightGreen);
                            break;

                        case ChangeType.Deleted:
                            tr.Text = line.Text;
                            tr.ApplyPropertyValue(TextElement.BackgroundProperty, Brushes.LightPink);
                            break;

                        case ChangeType.Modified:
                            tr.Text = line.Text;
                            tr.ApplyPropertyValue(TextElement.BackgroundProperty, Brushes.Goldenrod);
                            break;

                        case ChangeType.Imaginary:
                            tr.Text = "            ";
                            tr.ApplyPropertyValue(TextElement.BackgroundProperty, Brushes.Gray);
                            break;

                        case ChangeType.Unchanged:
                            tr.Text = line.Text;
                            tr.ApplyPropertyValue(TextElement.ForegroundProperty, Brushes.Black);
                            break;

                        default:
                            tr.Text = line.Text;
                            tr.ApplyPropertyValue(TextElement.ForegroundProperty, Brushes.White);
                            break;
                        }
                        tb[j].Document.Blocks.Add(p);
                    }
                }
            }
        }
            public void Will_build_diffModel_for_partially_different_documents()
            {
                string textOld = "1\n2\na\nb\nc\nd\n\n";
                string textNew = "1\n2\nz\ny\nx\nw\n";

                string[] textLinesOld = { "1", "2", "a", "b", "c", "d", "" };
                string[] textLinesNew = { "1", "2", "z", "y", "x", "w" };
                var      differ       = new Mock <IDiffer>();

                differ.Setup(x => x.CreateLineDiffs(textOld, textNew, true))
                .Returns(new DiffResult(textLinesOld, textLinesNew, new List <DiffBlock> {
                    new DiffBlock(2, 5, 2, 4)
                }));
                differ.Setup(x => x.CreateWordDiffs(It.IsAny <string>(), It.IsAny <string>(), false, It.IsAny <char[]>()))
                .Returns(new DiffResult(new string[0], new string[0], new List <DiffBlock>()));
                var builder = new SideBySideDiffBuilder(differ.Object);

                var bidiff = builder.BuildDiffModel(textOld, textNew);

                Assert.NotNull(bidiff);
                Assert.Equal(7, bidiff.OldText.Lines.Count);
                Assert.Equal(7, bidiff.NewText.Lines.Count);
                int i = 0;

                for (; i < 2; i++)
                {
                    Assert.Equal(textLinesNew[i], bidiff.NewText.Lines[i].Text);
                    Assert.Equal(ChangeType.Unchanged, bidiff.NewText.Lines[i].Type);
                    Assert.Equal(i + 1, bidiff.NewText.Lines[i].Position);

                    Assert.Equal(textLinesOld[i], bidiff.OldText.Lines[i].Text);
                    Assert.Equal(ChangeType.Unchanged, bidiff.OldText.Lines[i].Type);
                    Assert.Equal(i + 1, bidiff.OldText.Lines[i].Position);
                }

                for (; i < Math.Min(textLinesOld.Length, textLinesNew.Length); i++)
                {
                    Assert.Equal(textLinesOld[i], bidiff.OldText.Lines[i].Text);
                    Assert.Equal(ChangeType.Modified, bidiff.OldText.Lines[i].Type);
                    Assert.Equal(i + 1, bidiff.OldText.Lines[i].Position);

                    Assert.Equal(textLinesNew[i], bidiff.NewText.Lines[i].Text);
                    Assert.Equal(ChangeType.Modified, bidiff.NewText.Lines[i].Type);
                    Assert.Equal(i + 1, bidiff.NewText.Lines[i].Position);
                }

                if (textLinesOld.Length < textLinesNew.Length)
                {
                    for (int j = i; j < textLinesNew.Length; j++)
                    {
                        Assert.Equal(textLinesNew[j], bidiff.NewText.Lines[j].Text);
                        Assert.Equal(ChangeType.Inserted, bidiff.NewText.Lines[j].Type);
                        Assert.Equal(j + 1, bidiff.NewText.Lines[j].Position);

                        Assert.Null(bidiff.OldText.Lines[j].Text);
                        Assert.Equal(ChangeType.Imaginary, bidiff.OldText.Lines[j].Type);
                        Assert.False(bidiff.OldText.Lines[j].Position.HasValue);
                    }
                }
                else
                {
                    for (int j = i; j < textLinesOld.Length; j++)
                    {
                        Assert.Equal(textLinesOld[j], bidiff.OldText.Lines[j].Text);
                        Assert.Equal(ChangeType.Deleted, bidiff.OldText.Lines[j].Type);
                        Assert.Equal(j + 1, bidiff.OldText.Lines[j].Position);

                        Assert.Null(bidiff.NewText.Lines[j].Text);
                        Assert.Equal(ChangeType.Imaginary, bidiff.NewText.Lines[j].Type);
                        Assert.False(bidiff.NewText.Lines[j].Position.HasValue);
                    }
                }
            }
        private string ConstructEstimateCodeDiff(MethodDefinition method)
        {
            var decompilationOutput = new PlainTextOutput();

            try
            {
                _cSharpDecompiler.DecompileMethod(method, decompilationOutput, _decompilationOptions);
            }
            catch
            {
                return("\t\tNo decompilation available for mutated version.\n");
            }
            string newText    = decompilationOutput.ToString();
            var    model      = _differ.BuildDiffModel(_oldText, newText);
            string diffOutput = "\t\tApproximate source code difference from IL decompilation:\n";
            var    lines      = new SortedSet <int>();

            for (int i = 0; i < Math.Max(model.OldText.Lines.Count, model.NewText.Lines.Count); i++)
            {
                if ((i < model.OldText.Lines.Count && model.OldText.Lines[i].Type != ChangeType.Unchanged) ||
                    (i < model.NewText.Lines.Count && model.NewText.Lines[i].Type != ChangeType.Unchanged))
                {
                    lines.Add(i - 2);
                    lines.Add(i - 1);
                    lines.Add(i);
                    lines.Add(i + 1);
                    lines.Add(i + 2);
                }
            }
            int    lastLine = -1;
            string adds     = "";
            string takes    = "";

            foreach (var line in lines)
            {
                if (line < 0)
                {
                    continue;
                }
                if (line > lastLine + 1)
                {
                    diffOutput += string.Format("{1}{2}\t\t@@ {0} @@\n", line,
                                                takes, adds);
                    takes = "";
                    adds  = "";
                }
                if (line < model.OldText.Lines.Count)
                {
                    takes += string.Format("\t\t- {0}\n",
                                           (model.OldText.Lines[line].Text ?? "").Replace("\t", "  "));
                }
                if (line < model.NewText.Lines.Count)
                {
                    adds += string.Format("\t\t+ {0}\n",
                                          (model.NewText.Lines[line].Text ?? "").Replace("\t", "  "));
                }
                lastLine = line;
            }
            if (!string.IsNullOrEmpty(adds) || !string.IsNullOrEmpty(takes))
            {
                diffOutput += takes + adds;
            }
            return(diffOutput);
        }
            public void Can_compare_whitespace()
            {
                string textOld = "1\n 2\n3 \n 4 \n5";
                string textNew = "1\n2\n3\n4\n5";
                var    builder = new SideBySideDiffBuilder(new Differ());
                var    model   = builder.BuildDiffModel(textOld, textNew, ignoreWhitespace: false);

                Assert.Equal(
                    model.OldText.Lines,
                    new DiffPiece[]
                {
                    new DiffPiece("1", ChangeType.Unchanged, 1),
                    new DiffPiece(" 2", ChangeType.Modified, 2)
                    {
                        SubPieces =
                        {
                            new DiffPiece("",  ChangeType.Deleted,   1),
                            new DiffPiece(" ", ChangeType.Deleted,   2),
                            new DiffPiece("2", ChangeType.Unchanged, 3),
                        },
                    },
                    new DiffPiece("3 ", ChangeType.Modified, 3)
                    {
                        SubPieces =
                        {
                            new DiffPiece("3", ChangeType.Unchanged, 1),
                            new DiffPiece(" ", ChangeType.Deleted,   2),
                        },
                    },
                    new DiffPiece(" 4 ", ChangeType.Modified, 4)
                    {
                        SubPieces =
                        {
                            new DiffPiece("",  ChangeType.Deleted,   1),
                            new DiffPiece(" ", ChangeType.Deleted,   2),
                            new DiffPiece("4", ChangeType.Unchanged, 3),
                            new DiffPiece(" ", ChangeType.Deleted,   4),
                        },
                    },
                    new DiffPiece("5", ChangeType.Unchanged, 5),
                });
                Assert.Equal(
                    model.NewText.Lines,
                    new DiffPiece[]
                {
                    new DiffPiece("1", ChangeType.Unchanged, 1),
                    new DiffPiece("2", ChangeType.Modified, 2)
                    {
                        SubPieces =
                        {
                            new DiffPiece(null, ChangeType.Imaginary),
                            new DiffPiece(null, ChangeType.Imaginary),
                            new DiffPiece("2",  ChangeType.Unchanged,1),
                        },
                    },
                    new DiffPiece("3", ChangeType.Modified, 3)
                    {
                        SubPieces =
                        {
                            new DiffPiece("3",  ChangeType.Unchanged,  1),
                            new DiffPiece(null, ChangeType.Imaginary),
                        },
                    },
                    new DiffPiece("4", ChangeType.Modified, 4)
                    {
                        SubPieces =
                        {
                            new DiffPiece(null, ChangeType.Imaginary),
                            new DiffPiece(null, ChangeType.Imaginary),
                            new DiffPiece("4",  ChangeType.Unchanged,1),
                            new DiffPiece(null, ChangeType.Imaginary),
                        },
                    },
                    new DiffPiece("5", ChangeType.Unchanged, 5),
                });
            }
        private async Task DiffTwoFilesAsync(string file, FileCompareModel diffViewModel, StreamWriter streamWriter)
        {
            var title = GetSectionTitle("Diff Comparison");

            var builder = new SideBySideDiffBuilder(new Differ());

            if (!File.Exists(diffViewModel.RightPath) && !File.Exists(diffViewModel.LeftPath))
            {
                // use the repository item path in the message
                var html = title + WrapTableDefinition(BuildRow($"Could not locate file {diffViewModel.RightPath}.  A Diff Comparison was not generated"));

                streamWriter.Write(html);
                return;
            }

            if (!File.Exists(diffViewModel.RightPath) || !File.Exists(diffViewModel.LeftPath))
            {
                var html = title + WrapTableDefinition(BuildRow("Only One Version of this file is available.  A Diff Comparison was not generated"));

                streamWriter.Write(html);
                return;
            }

            // add the repository items path for the sub title.
            title += GetSubSectionTitle(file);

            var leftText  = "";
            var rightText = "";

            var sw = new System.Diagnostics.Stopwatch();

            sw.Start();

            using (var reader = File.OpenText(diffViewModel.LeftPath))
            {
                Log($"[AuditReports]:[Reading Left]:[Started]");
                leftText = await reader.ReadToEndAsync();

                Log($"[AuditReports]:[Reading Left]:[Completed]");
            }

            using (var reader = File.OpenText(diffViewModel.RightPath))
            {
                Log($"[AuditReports]:[Reading Right]:[Started]");
                rightText = await reader.ReadToEndAsync();

                Log($"[AuditReports]:[Reading Right]:[Completed]");
            }



            Log($"[AuditReports]:[BuildDiffModel]:[Started]");
            var diff = await Task.Run(() => { return(builder.BuildDiffModel(leftText, rightText)); });

            Log($"[AuditReports]:[BuildDiffModel]:[Completed]");
            var htmlBuilder = new Html.DiffHtml();



            var include = IncludeUnChangedText(diffViewModel.RightPath, diffViewModel.LeftPath);

            if (!include)
            {
                title += GetSubSectionTitle("Due to the size of the original files, the comparison will only show modified lines.");
            }

            await streamWriter.WriteLineAsync(title);


            Log($"[AuditReports]:[Build]:[Started]");
            await htmlBuilder.BuildAsync(diff, streamWriter, include);

            Log($"[AuditReports]:[Build]:[Completed]");

            Console.ForegroundColor = ConsoleColor.Green;
            sw.Stop();
            Log($"[AuditReports]:[{nameof(DiffTwoFilesAsync)}]:[Completed In]:[{ElapsedTime(sw.Elapsed)}]");
            Console.ResetColor();
        }
        //-----------------------------------------------------------------------
        public void DoTransform()
        {
            var preview = new TransformPreview();

            var projectDir = Path.GetDirectoryName(Workspace.ProjectRoot);
            var files      = Directory.EnumerateFiles(projectDir, "*", SearchOption.AllDirectories).ToList();

            foreach (var file in files)
            {
                var ext = Path.GetExtension(file);

                if (ext == ".xml" || ext == ".json" || ext == ".yaml" || Workspace.SupportedExtensionMap.ContainsKey(ext))
                {
                    try
                    {
                        var doc         = XDocument.Load(file);
                        var transformed = DataTransformer.TransformDocument(doc.Root);
                        var asString    = new StringBuilder();

                        XmlWriterSettings settings = new XmlWriterSettings
                        {
                            Indent             = true,
                            IndentChars        = "\t",
                            NewLineChars       = "\r\n",
                            NewLineHandling    = NewLineHandling.Replace,
                            OmitXmlDeclaration = true,
                            Encoding           = new UTF8Encoding(false)
                        };

                        using (XmlWriter writer = XmlTextWriter.Create(asString, settings))
                        {
                            doc.Save(writer);
                        }

                        var original    = File.ReadAllText(file);
                        var newContents = asString.ToString();

                        if (transformed && original != newContents)
                        {
                            var builder = new SideBySideDiffBuilder(new Differ());
                            var diff    = builder.BuildDiffModel(original, newContents);

                            if (diff.NewText.Lines.Any(e => e.Type != ChangeType.Unchanged) || diff.OldText.Lines.Any(e => e.Type != ChangeType.Unchanged))
                            {
                                preview.Files.Add(new Tuple <string, string, string, SideBySideDiffModel>(file, Path.GetFileNameWithoutExtension(file), newContents, diff));
                            }
                        }
                    }
                    catch (Exception) { }
                }
            }

            if (preview.Files.Count == 0)
            {
                Message.Show("No matching files found in project", "Completed transform");
            }
            else
            {
                Preview = preview;
                RaisePropertyChangedEvent(nameof(Preview));
            }
        }
Example #25
0
        /// <summary>
        /// 差分比較情報を作成
        /// </summary>
        private SideBySideDiffModel CreateDiff()
        {
            var diff = new SideBySideDiffBuilder(new Differ());

            return(diff.BuildDiffModel(pathModel.InputFileName, pathModel.OutputFileName));
        }
            public void Will_build_diffModel_for_partially_different_documents()
            {
                string textOld = "1\n2\na\nb\nc\nd\n\n";
                string textNew = "1\n2\nz\ny\nx\nw\n";

                string[] textLinesOld = { "1", "2", "a", "b", "c", "d", "" };
                string[] textLinesNew = { "1", "2", "z", "y", "x", "w" };
                var      builder      = new SideBySideDiffBuilder();

                var bidiff = builder.BuildDiffModel(textOld, textNew);

                Assert.NotNull(bidiff);
                Assert.Equal(8, bidiff.OldText.Lines.Count);
                Assert.Equal(8, bidiff.NewText.Lines.Count);
                int i = 0;

                for (; i < 2; i++)
                {
                    Assert.Equal(textLinesNew[i], bidiff.NewText.Lines[i].Text);
                    Assert.Equal(ChangeType.Unchanged, bidiff.NewText.Lines[i].Type);
                    Assert.Equal(i + 1, bidiff.NewText.Lines[i].Position);

                    Assert.Equal(textLinesOld[i], bidiff.OldText.Lines[i].Text);
                    Assert.Equal(ChangeType.Unchanged, bidiff.OldText.Lines[i].Type);
                    Assert.Equal(i + 1, bidiff.OldText.Lines[i].Position);
                }

                for (; i < Math.Min(textLinesOld.Length, textLinesNew.Length); i++)
                {
                    Assert.Equal(textLinesOld[i], bidiff.OldText.Lines[i].Text);
                    Assert.Equal(ChangeType.Modified, bidiff.OldText.Lines[i].Type);
                    Assert.Equal(i + 1, bidiff.OldText.Lines[i].Position);

                    Assert.Equal(textLinesNew[i], bidiff.NewText.Lines[i].Text);
                    Assert.Equal(ChangeType.Modified, bidiff.NewText.Lines[i].Type);
                    Assert.Equal(i + 1, bidiff.NewText.Lines[i].Position);
                }

                if (textLinesOld.Length < textLinesNew.Length)
                {
                    for (int j = i; j < textLinesNew.Length; j++)
                    {
                        Assert.Equal(textLinesNew[j], bidiff.NewText.Lines[j].Text);
                        Assert.Equal(ChangeType.Inserted, bidiff.NewText.Lines[j].Type);
                        Assert.Equal(j + 1, bidiff.NewText.Lines[j].Position);

                        Assert.Null(bidiff.OldText.Lines[j].Text);
                        Assert.Equal(ChangeType.Imaginary, bidiff.OldText.Lines[j].Type);
                        Assert.False(bidiff.OldText.Lines[j].Position.HasValue);
                    }
                }
                else
                {
                    for (int j = i; j < textLinesOld.Length; j++)
                    {
                        Assert.Equal(textLinesOld[j], bidiff.OldText.Lines[j].Text);
                        Assert.Equal(ChangeType.Deleted, bidiff.OldText.Lines[j].Type);
                        Assert.Equal(j + 1, bidiff.OldText.Lines[j].Position);

                        Assert.Null(bidiff.NewText.Lines[j].Text);
                        Assert.Equal(ChangeType.Imaginary, bidiff.NewText.Lines[j].Type);
                        Assert.False(bidiff.NewText.Lines[j].Position.HasValue);
                    }
                }

                Assert.True(bidiff.OldText.HasDifferences && bidiff.NewText.HasDifferences);
            }
Example #27
0
        // 创建展示两个 OPAC 记录差异的 HTML 字符串
        // parameters:
        //      strNewText  如果为 "",表示内容全部被删除,依然会输出对照格式;如果为 null,表示只输出左边的部分
        // return:
        //      -1  出错
        //      0   成功。两边相等
        //      1   两边不相等
        public static int DiffOpacHtml(
            string strOldText,
            string strNewText,
            out string strHtml,
            out string strError)
        {
            strError = "";
            strHtml  = "";

            if (string.IsNullOrEmpty(strOldText) == true && string.IsNullOrEmpty(strNewText) == true)
            {
                return(0);
            }

            var marc_differ      = new Differ();
            var marc_builder     = new SideBySideDiffBuilder(marc_differ);
            var marc_diff_result = marc_builder.BuildDiffModel(strOldText,
                                                               strNewText == null? "" : strNewText);

            Debug.Assert(marc_diff_result.OldText.Lines.Count == marc_diff_result.NewText.Lines.Count, "");

            /*
             * public enum ChangeType
             * {
             * Unchanged,
             * Deleted,
             * Inserted,
             * Imaginary,
             * Modified
             * }
             * */

            bool bChanged = false;

            StringBuilder strResult = new StringBuilder("\r\n<table class='marc'>", 4096);

            for (int index = 0; index < marc_diff_result.NewText.Lines.Count; index++)
            {
                var newline = marc_diff_result.NewText.Lines[index];
                var oldline = marc_diff_result.OldText.Lines[index];

                if (string.IsNullOrEmpty(newline.Text) == true &&
                    string.IsNullOrEmpty(oldline.Text) == true)
                {
                    continue;
                }

                if (oldline.Type != ChangeType.Unchanged ||
                    newline.Type != ChangeType.Unchanged)
                {
                    bChanged = true;
                }

                string strLineClass = "datafield";
                if (strNewText == null)
                {
                    strResult.Append("\r\n<tr class='" + strLineClass + "'>");
                    // 创建一个字段的 HTML 局部 三个 <td>
                    strResult.Append(BuildOpacFieldHtml(ChangeType.Unchanged, oldline.Text));
                    strResult.Append("\r\n</tr>");
                    continue;
                }

                strResult.Append("\r\n<tr class='" + strLineClass + "'>");
                // 创建一个字段的 HTML 局部 三个 <td>
                strResult.Append(BuildOpacFieldHtml(oldline.Type, oldline.Text));
                strResult.Append(SEP);
                strResult.Append(BuildOpacFieldHtml(newline.Type, newline.Text));
                strResult.Append("\r\n</tr>");
            }

            strResult.Append("</table>");
            strHtml = strResult.ToString();

            if (bChanged == false)
            {
                return(0);
            }

            return(1);
        }
Example #28
0
        // 创建展示两个 MARC 记录差异的 HTML 字符串
        // return:
        //      -1  出错
        //      0   成功
        public static int DiffHtml(
            string strOldTitle,
            string strOldMarc,
            string strOldFragmentXml,
            string strOldImageFragment,
            string strNewTitle,
            string strNewMarc,
            string strNewFragmentXml,
            string strNewImageFragment,
            out string strHtml,
            out string strError)
        {
            strError = "";
            strHtml  = "";
            // int nRet = 0;

            if (string.IsNullOrEmpty(strOldMarc) == true && string.IsNullOrEmpty(strNewMarc) == true)
            {
                return(0);
            }

            string strOldHeader = "";
            string strNewHeader = "";
            string strOldBody   = "";
            string strNewBody   = "";

            SplitMarc(strOldMarc,
                      out strOldHeader,
                      out strOldBody);
            SplitMarc(strNewMarc,
                      out strNewHeader,
                      out strNewBody);

            if (strOldHeader.Length < 24)
            {
                strOldHeader = strOldHeader.PadRight(24, '?');
            }
            if (strNewHeader.Length < 24)
            {
                strNewHeader = strNewHeader.PadRight(24, '?');
            }

            var marc_differ      = new MarcDiffer();
            var marc_builder     = new MarcDiffBuilder(marc_differ);
            var marc_diff_result = marc_builder.BuildDiffModel(strOldBody, strNewBody);

            Debug.Assert(marc_diff_result.OldText.Lines.Count == marc_diff_result.NewText.Lines.Count, "");

            /*
             * public enum ChangeType
             * {
             * Unchanged,
             * Deleted,
             * Inserted,
             * Imaginary,
             * Modified
             * }
             * */

            StringBuilder strResult = new StringBuilder("\r\n<table class='marc'>", 4096);

            if (string.IsNullOrEmpty(strOldTitle) == false ||
                string.IsNullOrEmpty(strNewTitle) == false)
            {
                string strLineClass = "header";
                strResult.Append("\r\n<tr class='" + strLineClass + "'>");

                strResult.Append(BuildHeaderHtml(false, strOldTitle));
                strResult.Append(SEP);
                strResult.Append(BuildHeaderHtml(false, strNewTitle));
                strResult.Append("\r\n</tr>");
            }


            {
                string strLineClass = "header";
                bool   bModified    = strOldHeader != strNewHeader;
                strResult.Append("\r\n<tr class='" + strLineClass + "'>");

                strResult.Append(BuildHeaderHtml(bModified, strOldHeader));
                strResult.Append(SEP);
                strResult.Append(BuildHeaderHtml(bModified, strNewHeader));
                strResult.Append("\r\n</tr>");
            }

            if (string.IsNullOrEmpty(strOldImageFragment) == false ||
                string.IsNullOrEmpty(strNewImageFragment) == false)
            {
                string strLineClass = "header";
                strResult.Append("\r\n<tr class='" + strLineClass + "'>");

                strResult.Append(GetImageHtml(strOldImageFragment));
                strResult.Append(SEP);
                strResult.Append(GetImageHtml(strNewImageFragment));
                strResult.Append("\r\n</tr>");
            }


            for (int index = 0; index < marc_diff_result.NewText.Lines.Count; index++)
            {
                var newline = marc_diff_result.NewText.Lines[index];
                var oldline = marc_diff_result.OldText.Lines[index];

                if (string.IsNullOrEmpty(newline.Text) == true &&
                    string.IsNullOrEmpty(oldline.Text) == true)
                {
                    continue;
                }

                string strLineClass = "datafield";
                strResult.Append("\r\n<tr class='" + strLineClass + "'>");
                // 创建一个字段的 HTML 局部 三个 <td>
                strResult.Append(BuildFieldHtml(oldline.Type, oldline.Text));
                strResult.Append(SEP);
                strResult.Append(BuildFieldHtml(newline.Type, newline.Text));
                strResult.Append("\r\n</tr>");

#if NO
                if (newline.Type == ChangeType.Unchanged)
                {
                }
                else if (newline.Type == ChangeType.Inserted)
                {
                }
                else if (newline.Type == ChangeType.Modified)
                {
                }
                else if (oldline.Type == ChangeType.Deleted)
                {
                }
#endif
            }

#if NO
            if (string.IsNullOrEmpty(strOldFragmentXml) == false || string.IsNullOrEmpty(strNewFragmentXml) == false)
            {
                var xml_differ      = new Differ();
                var xml_builder     = new SideBySideDiffBuilder(xml_differ);
                var xml_diff_result = xml_builder.BuildDiffModel(GetComparableXmlString(strOldFragmentXml), GetComparableXmlString(strNewFragmentXml));

                Debug.Assert(xml_diff_result.OldText.Lines.Count == xml_diff_result.NewText.Lines.Count, "");

                for (int index = 0; index < xml_diff_result.NewText.Lines.Count; index++)
                {
                    var newline = xml_diff_result.NewText.Lines[index];
                    var oldline = xml_diff_result.OldText.Lines[index];

                    string strLineClass = "datafield";

                    if (newline.Type == ChangeType.Modified)
                    {
                    }

                    strResult.Append("\r\n<tr class='" + strLineClass + "'>");
                    // 创建一个 XML 字段的 HTML 局部 三个 <td>
                    strResult.Append(BuildFragmentFieldHtml(oldline.Type, oldline.Text));
                    strResult.Append(SEP);
                    strResult.Append(BuildFragmentFieldHtml(newline.Type, newline.Text));
                    strResult.Append("\r\n</tr>");
                }
            }
#endif

            if (string.IsNullOrEmpty(strOldFragmentXml) == false || string.IsNullOrEmpty(strNewFragmentXml) == false)
            {
                string strLineClass = "sepline";
                strResult.Append("\r\n<tr class='" + strLineClass + "'>");
                strResult.Append("<td class='sepline' colspan='3'>&nbsp;</td>");
                strResult.Append("<td class='cross'>&nbsp;</td>");
                strResult.Append("<td class='sepline' colspan='3'>&nbsp;</td>");
                strResult.Append("\r\n</tr>");
            }

            strResult.Append(DiffXml(
                                 0,
                                 strOldFragmentXml,
                                 XmlNodeType.Element,
                                 strNewFragmentXml,
                                 XmlNodeType.Element));

            strResult.Append("</table>");
            strHtml = strResult.ToString();

            return(0);
        }
            public void Will_build_diffModel_for_unique_strings()
            {
                string textOld = "a\nb\nc\nd\n\n";
                string textNew = "z\ny\nx\nw\n";

                string[] textLinesOld = { "a", "b", "c", "d", "" };
                string[] textLinesNew = { "z", "y", "x", "w" };
                var      differ       = new Mock <IDiffer>();

                differ.Setup(x => x.CreateDiffs(textOld, textNew, true, false, It.IsNotNull <IChunker>()))
                .Returns(new DiffResult(textLinesOld, textLinesNew, new List <DiffBlock> {
                    new DiffBlock(0, 5, 0, 4)
                }));
                differ.Setup(x => x.CreateDiffs(It.IsAny <string>(), It.IsAny <string>(), false, false, It.IsNotNull <IChunker>()))
                .Returns(new DiffResult(new string[0], new string[0], new List <DiffBlock>()));
                var builder = new SideBySideDiffBuilder(differ.Object);

                var bidiff = builder.BuildDiffModel(textOld, textNew);

                Assert.NotNull(bidiff);
                Assert.Equal(5, bidiff.OldText.Lines.Count);
                Assert.Equal(5, bidiff.NewText.Lines.Count);
                int i = 0;

                for (; i < Math.Min(textLinesOld.Length, textLinesNew.Length); i++)
                {
                    Assert.Equal(textLinesOld[i], bidiff.OldText.Lines[i].Text);
                    Assert.Equal(ChangeType.Modified, bidiff.OldText.Lines[i].Type);
                    Assert.Equal(i + 1, bidiff.OldText.Lines[i].Position);

                    Assert.Equal(textLinesNew[i], bidiff.NewText.Lines[i].Text);
                    Assert.Equal(ChangeType.Modified, bidiff.NewText.Lines[i].Type);
                    Assert.Equal(i + 1, bidiff.NewText.Lines[i].Position);
                }

                if (textLinesOld.Length < textLinesNew.Length)
                {
                    for (int j = i; j < textLinesNew.Length; j++)
                    {
                        Assert.Equal(textLinesNew[j], bidiff.NewText.Lines[j].Text);
                        Assert.Equal(ChangeType.Inserted, bidiff.NewText.Lines[j].Type);
                        Assert.Equal(j + 1, bidiff.NewText.Lines[j].Position);

                        Assert.Null(bidiff.OldText.Lines[j].Text);
                        Assert.Equal(ChangeType.Imaginary, bidiff.OldText.Lines[j].Type);
                        Assert.False(bidiff.OldText.Lines[j].Position.HasValue);
                    }
                }
                else
                {
                    for (int j = i; j < textLinesOld.Length; j++)
                    {
                        Assert.Equal(textLinesOld[j], bidiff.OldText.Lines[j].Text);
                        Assert.Equal(ChangeType.Deleted, bidiff.OldText.Lines[j].Type);
                        Assert.Equal(j + 1, bidiff.OldText.Lines[j].Position);

                        Assert.Null(bidiff.NewText.Lines[j].Text);
                        Assert.Equal(ChangeType.Imaginary, bidiff.NewText.Lines[j].Type);
                        Assert.False(bidiff.NewText.Lines[j].Position.HasValue);
                    }
                }

                Assert.True(bidiff.OldText.HasDifferences && bidiff.NewText.HasDifferences);
            }
Example #30
0
        static string DiffXml(
            int nLevel,
            string strOldFragmentXml,
            XmlNodeType old_nodetype,
            string strNewFragmentXml,
            XmlNodeType new_nodetype)
        {
            if (string.IsNullOrEmpty(strOldFragmentXml) == true && string.IsNullOrEmpty(strNewFragmentXml) == true)
            {
                return("");
            }

            if (old_nodetype != XmlNodeType.Element || new_nodetype != XmlNodeType.Element)
            {
                if (old_nodetype == XmlNodeType.Element)
                {
                    strOldFragmentXml = GetIndentXml(strOldFragmentXml);
                }
                if (new_nodetype == XmlNodeType.Element)
                {
                    strNewFragmentXml = GetIndentXml(strNewFragmentXml);
                }
                return(GetPlanTextDiffHtml(
                           nLevel,
                           strOldFragmentXml,
                           strNewFragmentXml));
            }

            string         strOldChildren    = "";
            string         strOldBegin       = "";
            string         strOldEnd         = "";
            List <XmlNode> old_childnodes    = null;
            string         strOldElementName = "";

            GetComparableXmlString(strOldFragmentXml,
                                   out strOldChildren,
                                   out old_childnodes,
                                   out strOldElementName,
                                   out strOldBegin,
                                   out strOldEnd);

            string         strNewChildren    = "";
            string         strNewBegin       = "";
            string         strNewEnd         = "";
            List <XmlNode> new_childnodes    = null;
            string         strNewElementName = "";

            GetComparableXmlString(strNewFragmentXml,
                                   out strNewChildren,
                                   out new_childnodes,
                                   out strNewElementName,
                                   out strNewBegin,
                                   out strNewEnd);

            bool bSpecialCompare = false;   // 是否属于特殊情况: 根元素名不相同,但仍需要比较下级

            if (strOldElementName != strNewElementName &&
                nLevel == 0)
            {
                bSpecialCompare = true;
            }

            if (strOldElementName != strNewElementName && bSpecialCompare == false)
            {
                // 元素名不一样了并且不是根级别,就没有必要做细节比较了
                // 意思是说如果是根级别,即便根元素名不一样,也要比较其下级
                if (old_nodetype == XmlNodeType.Element)
                {
                    strOldFragmentXml = GetIndentXml(strOldFragmentXml);
                }
                if (new_nodetype == XmlNodeType.Element)
                {
                    strNewFragmentXml = GetIndentXml(strNewFragmentXml);
                }
                return(GetPlanTextDiffHtml(
                           nLevel,
                           strOldFragmentXml,
                           strNewFragmentXml));
            }

            string        strLineClass = "datafield";
            StringBuilder strResult    = new StringBuilder(4096);

            if (nLevel > 0 || bSpecialCompare == true)
            {
                ChangeType begin_type = ChangeType.Unchanged;
                if (strOldBegin != strNewBegin)
                {
                    begin_type = ChangeType.Modified;
                }

                // Begin
                strResult.Append("\r\n<tr class='" + strLineClass + "'>");
                strResult.Append(BuildFragmentFieldHtml(nLevel, begin_type, strOldBegin));
                strResult.Append(SEP);
                strResult.Append(BuildFragmentFieldHtml(nLevel, begin_type, strNewBegin));
                strResult.Append("\r\n</tr>");
            }

            // return "\r\n<td class='content' colspan='3'></td>";

            if (string.IsNullOrEmpty(strOldChildren) == false || string.IsNullOrEmpty(strNewChildren) == false)
            {
                var xml_differ      = new Differ();
                var xml_builder     = new SideBySideDiffBuilder(xml_differ);
                var xml_diff_result = xml_builder.BuildDiffModel(strOldChildren, strNewChildren);

                Debug.Assert(xml_diff_result.OldText.Lines.Count == xml_diff_result.NewText.Lines.Count, "");
                int old_index = 0;
                int new_index = 0;
                for (int index = 0; index < xml_diff_result.NewText.Lines.Count; index++)
                {
                    var newline = xml_diff_result.NewText.Lines[index];
                    var oldline = xml_diff_result.OldText.Lines[index];

                    XmlNode new_node = null;
                    if (newline.Type != ChangeType.Imaginary)
                    {
                        new_node = new_childnodes[new_index++];
                    }

                    XmlNode old_node = null;
                    if (oldline.Type != ChangeType.Imaginary)
                    {
                        old_node = old_childnodes[old_index++];
                    }

                    if (newline.Type == ChangeType.Modified)
                    {
                        strResult.Append(DiffXml(nLevel + 1,
                                                 oldline.Text,
                                                 old_node.NodeType,
                                                 newline.Text,
                                                 new_node.NodeType));
                        continue;
                    }

                    string strOldText = "";
                    if (old_node != null && old_node.NodeType == XmlNodeType.Element)
                    {
                        strOldText = GetIndentXml(oldline.Text);
                    }
                    else
                    {
                        strOldText = oldline.Text;
                    }

                    string strNewText = "";
                    if (new_node != null && new_node.NodeType == XmlNodeType.Element)
                    {
                        strNewText = GetIndentXml(newline.Text);
                    }
                    else
                    {
                        strNewText = newline.Text;
                    }

                    strResult.Append("\r\n<tr class='" + strLineClass + "'>");
                    // 创建一个 XML 字段的 HTML 局部 三个 <td>
                    strResult.Append(BuildFragmentFieldHtml(nLevel + 1, oldline.Type, strOldText));
                    strResult.Append(SEP);
                    strResult.Append(BuildFragmentFieldHtml(nLevel + 1, newline.Type, strNewText));
                    strResult.Append("\r\n</tr>");
                }
            }

            if (nLevel > 0 || bSpecialCompare == true)
            {
                ChangeType end_type = ChangeType.Unchanged;
                if (strOldEnd != strNewEnd)
                {
                    end_type = ChangeType.Modified;
                }

                // End
                strResult.Append("\r\n<tr class='" + strLineClass + "'>");
                strResult.Append(BuildFragmentFieldHtml(nLevel, end_type, strOldEnd));
                strResult.Append(SEP);
                strResult.Append(BuildFragmentFieldHtml(nLevel, end_type, strNewEnd));
                strResult.Append("\r\n</tr>");
            }

            return(strResult.ToString());
        }