public static int GetLevel(string Source, string Destination) { Differ DiffMaker = new Differ(); SideBySideDiffBuilder SideBySideDiffer = new SideBySideDiffBuilder(DiffMaker); SideBySideDiffModel SideBySideDiffResult = SideBySideDiffer.BuildDiffModel(Source, Destination); return GetLevel(SideBySideDiffResult, Source, Destination); }
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()); 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); }
/// <summary> /// measure differential between two files /// </summary> public static DiffCounter Count( string originalFile, string modifiedFile) { var original = File.ReadAllText(@originalFile); var modified = File.ReadAllText(@modifiedFile); var d = new Differ(); var counter = new DiffCounter(); var side = new SideBySideDiffBuilder(d); var result = side.BuildDiffModel(original, modified); // added, modified, and unmodified at modified file foreach (var line in result.NewText.Lines) { if (line.Type == ChangeType.Inserted) { counter.AddedCount++; } if (line.Type == ChangeType.Modified) { counter.ModifiedCount++; } if (line.Type == ChangeType.Unchanged) { counter.EqualCount++; } } // deleted from original file foreach (var line in result.OldText.Lines) { if (line.Type == ChangeType.Deleted) { counter.DeletedCount++; } } return counter; }
public void Will_build_diffModel_for_duplicate_strings() { string text = "a\nb\nc\nd\n\n"; string[] textLines = new[] {"a", "b", "c", "d", ""}; var differ = new Mock<IDiffer>(); differ.Setup(x => x.CreateLineDiffs(text, text, true)) .Returns(new DiffResult(textLines, textLines, new List<DiffBlock>())); 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(text, text); Assert.NotNull(bidiff); Assert.Equal(textLines.Length, bidiff.OldText.Lines.Count); Assert.Equal(textLines.Length, bidiff.NewText.Lines.Count); for (int i = 0; i < textLines.Length; i++) { Assert.Equal(textLines[i], bidiff.OldText.Lines[i].Text); Assert.Equal(ChangeType.Unchanged, bidiff.OldText.Lines[i].Type); Assert.Equal(i + 1, bidiff.OldText.Lines[i].Position); Assert.Equal(textLines[i], bidiff.NewText.Lines[i].Text); Assert.Equal(ChangeType.Unchanged, bidiff.NewText.Lines[i].Type); Assert.Equal(i + 1, bidiff.NewText.Lines[i].Position); } }
public void Will_throw_is_NewText_is_null() { var differ = new Mock<IDiffer>(); var builder = new SideBySideDiffBuilder(differ.Object); var ex = Record.Exception(() => builder.BuildDiffModel("asa", null)); Assert.IsType<ArgumentNullException>(ex); var an = (ArgumentNullException) ex; Assert.Equal("newText", an.ParamName); }
private void RunFileDiff(string fileA, string fileB) { var textA = LoadText(fileA); var textB = LoadText(fileB); var differ = new SideBySideDiffBuilder(new Differ()); var diffResult = differ.BuildDiffModel(textA, textB); var formattedData = _formatter.Format(diffResult); _writer.Write(formattedData); }
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; }
public SideBySideFlowDocumentDiffGenerator(string leftText, string rightText) { Initialise(); var differ = new SideBySideDiffBuilder(new Differ()); var diffRes = differ.BuildDiffModel(leftText, rightText); LeftDocument = GenerateFlowDocument(diffRes.OldText); RightDocument = GenerateFlowDocument(diffRes.NewText); FirstModifiedLineVerticalOffset = diffRes.OldText.Lines.FindIndex(l => l.Type != ChangeType.Unchanged)*_lineHeight; }
public void GenerateDiffView() { if (_inDiff) return; lock (_mutex) { if (_inDiff) return; _inDiff = true; } _differ = new SideBySideDiffBuilder(new Differ()); var diffRes = _differ.BuildDiffModel(_leftText, _rightText); FirstModifiedLine = diffRes.NewText.Lines.FindIndex(l => l.Type != ChangeType.Unchanged); GenerateDiffPanes(diffRes.OldText, diffRes.NewText); _inDiff = false; }
public void Will_pass_correct_word_separators_to_create_word_diff() { string text = "a\nb\nc\nd\n\n"; string[] textLines = new[] {"a", "b", "c", "d", ""}; char[] chars = null; var differ = new Mock<IDiffer>(); differ.Setup(x => x.CreateLineDiffs(text, text, true)) .Returns(new DiffResult(textLines, textLines, new List<DiffBlock> {new DiffBlock(1, 1, 1, 1)})); 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>())) .Callback<string, string, bool, char[]>((a, b, c, d) => chars = d); var builder = new SideBySideDiffBuilder(differ.Object); builder.BuildDiffModel(text, text); Assert.Equal(SideBySideDiffBuilder.WordSeparaters.Length, chars.Length); foreach (var c in SideBySideDiffBuilder.WordSeparaters) { Assert.Contains(c, chars); } }
public void Will_build_diffModel_when_newText_is_empty() { string textNew = ""; string textOld = "z\ny\nx\nw\n"; string[] textLinesNew = new string[] {}; string[] textLinesOld = new[] {"z", "y"}; var differ = new Mock<IDiffer>(); differ.Setup(x => x.CreateLineDiffs(textOld, textNew, true)) .Returns(new DiffResult(textLinesOld, textLinesNew, new List<DiffBlock> {new DiffBlock(0, 2, 0, 0)})); 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 < 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); } }
public virtual ActionResult Diff(string folderName, string parentFolder, string uuid, int v1, int v2) { TextFolder textFolder = new TextFolder(Repository, folderName).AsActual(); var schema = textFolder.GetSchema().AsActual(); 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); }
// 创建展示两个 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; }
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(); }
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 = new[] {"1", "2", "a", "b", "c", "d", ""}; string[] textLinesNew = new[] {"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); } } }
public async Task<ActionResult> CompareBlobs(Errorable<BlobID.Partial> epida, Errorable<BlobID.Partial> epidb) { if (epida.HasErrors || epidb.HasErrors) return Json(new { errors = (epida.Errors + epidb.Errors).ToJSON() }, JsonRequestBehavior.AllowGet); // Resolve the partial IDs: var eids = await cms.blrepo.ResolvePartialIDs(epida.Value, epidb.Value); if (eids[0].HasErrors || eids[1].HasErrors) return Json(new { errors = (eids[0].Errors + eids[1].Errors).ToJSON() }, JsonRequestBehavior.AllowGet); BlobID idA = eids[0].Value; BlobID idB = eids[1].Value; // Get the Blobs: var ebls = await cms.blrepo.GetBlobs(idA, idB); if (ebls[0].HasErrors || ebls[1].HasErrors) return Json(new { errors = (ebls[0].Errors + ebls[1].Errors).ToJSON() }, JsonRequestBehavior.AllowGet); IStreamedBlob blA = ebls[0].Value, blB = ebls[1].Value; // Stream in both blobs' contents to string values: var etextA = await blA.ReadStreamAsync<string>(async st => { using (var sr = new StreamReader(st, Encoding.UTF8)) return (Errorable<string>)await sr.ReadToEndAsync(); }); if (etextA.HasErrors) return ErrorJson(etextA); var etextB = await blB.ReadStreamAsync<string>(async st => { using (var sr = new StreamReader(st, Encoding.UTF8)) return (Errorable<string>)await sr.ReadToEndAsync(); }); if (etextB.HasErrors) return ErrorJson(etextB); // TODO: update to a better diff engine that supports merging... // Create a diff engine: IDiffer differ = new Differ(); ISideBySideDiffBuilder builder = new SideBySideDiffBuilder(differ); // Run the diff engine to get the output model: // NOTE: I would prefer it to read in via a Stream but perhaps that is not possible given the algorithm implemented. var sxs = builder.BuildDiffModel(etextA.Value, etextB.Value); // Return the result as JSON: return Json(sxs.ToJSON(), JsonRequestBehavior.AllowGet); }
public static SideBySideDiffModel GetDiff(string Source, string Destination) { Differ DiffMaker = new Differ(); SideBySideDiffBuilder SideBySideDiffer = new SideBySideDiffBuilder(DiffMaker); return SideBySideDiffer.BuildDiffModel(Source, Destination); }
public void Will_build_diffModel_for_partially_different_lines() { string textOld = "m is h"; string textNew = "m ai is n h"; string[] textLinesOld = new[] {"m is h"}; string[] textLinesNew = new[] {"m ai is n h"}; var differ = new Mock<IDiffer>(); differ.Setup(x => x.CreateLineDiffs(textOld, textNew, true)) .Returns(new DiffResult(textLinesOld, textLinesNew, new List<DiffBlock> {new DiffBlock(0, 1, 0, 1)})); differ.Setup(x => x.CreateWordDiffs(It.IsAny<string>(), It.IsAny<string>(), false, It.IsAny<char[]>())) .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.Equal(1, bidiff.OldText.Lines.Count); Assert.Equal(1, bidiff.NewText.Lines.Count); Assert.Equal(bidiff.NewText.Lines[0].SubPieces[0].Type, ChangeType.Unchanged); Assert.Equal(bidiff.NewText.Lines[0].SubPieces[1].Type, ChangeType.Inserted); Assert.Equal(bidiff.NewText.Lines[0].SubPieces[2].Type, ChangeType.Unchanged); Assert.Equal(bidiff.NewText.Lines[0].SubPieces[3].Type, ChangeType.Inserted); Assert.Equal(bidiff.NewText.Lines[0].SubPieces[4].Type, ChangeType.Unchanged); Assert.Equal(bidiff.OldText.Lines[0].SubPieces[0].Type, ChangeType.Unchanged); Assert.Equal(bidiff.OldText.Lines[0].SubPieces[1].Type, ChangeType.Imaginary); Assert.Equal(bidiff.OldText.Lines[0].SubPieces[2].Type, ChangeType.Unchanged); Assert.Equal(bidiff.OldText.Lines[0].SubPieces[3].Type, ChangeType.Imaginary); Assert.Equal(bidiff.OldText.Lines[0].SubPieces[4].Type, ChangeType.Unchanged); }
// 创建展示两个 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'> </td>"); strResult.Append("<td class='cross'> </td>"); strResult.Append("<td class='sepline' colspan='3'> </td>"); strResult.Append("\r\n</tr>"); } strResult.Append(DiffXml( 0, strOldFragmentXml, XmlNodeType.Element, strNewFragmentXml, XmlNodeType.Element)); strResult.Append("</table>"); strHtml = strResult.ToString(); return 0; }