public class CrossReferenceAddingEvaluator : IReplacingCallback
{
private readonly string mStartBookmarkNumber;
internal CrossReferenceAddingEvaluator(string correctedBookMarkNumber)
{
mStartBookmarkNumber = correctedBookMarkNumber;
}
/// <summary>
/// This Function is used to get the matching node run.
/// </summary>
/// <param name="run"></param>
/// <param name="position"></param>
/// <returns></returns>
private static Run SplitRun(Run run, int position)
{
try
{
Run afterRun = (Run)run.Clone(true);
afterRun.Text = run.Text.Substring(position);
run.Text = run.Text.Substring(0, position);
run.ParentNode.InsertAfter(afterRun, run);
return afterRun;
}
catch (Exception ex)
{
ex.SplunkException();
return null;
}
}
/// <summary>
/// This Function is used to add the ref field to the matched string.
/// </summary>
/// <param name="args"></param>
/// <returns></returns>
ReplaceAction IReplacingCallback.Replacing(ReplacingArgs args)
{
try
{
// This is a Run node that contains either the beginning or the complete match.
Node currentNode = args.MatchNode;
Node prevNodeVal = currentNode;
// The first (and may be the only) run can contain text before the match,
// In this case it is necessary to split the run.
if (args.MatchOffset > 0)
currentNode = SplitRun((Aspose.Words.Run)currentNode, args.MatchOffset);
// This array is used to store all nodes of the match for further highlighting.
List<Run> runs = new List<Run>();
// Find all runs that contain parts of the match string.
int remainingLength = args.Match.Value.Length;
while (
(remainingLength > 0) &&
(currentNode != null) &&
(currentNode.GetText().Length <= remainingLength))
{
runs.Add((Run)currentNode);
remainingLength = remainingLength - currentNode.GetText().Length;
prevNodeVal = currentNode;
// Select the next Run node.
// Have to loop because there could be other nodes such as BookmarkStart etc.
do
{
currentNode = currentNode.NextSibling;
}
while ((currentNode != null) && (currentNode.NodeType != NodeType.Run));
}
// Split the last run that contains the match if there is any text left.
if ((currentNode != null) && (remainingLength > 0))
{
SplitRun((Aspose.Words.Run)currentNode, remainingLength);
runs.Add((Run)currentNode);
}
DocumentBuilder oDocBuild = new DocumentBuilder(args.MatchNode.Document as Document);
// Check if the replaced text contains a hyperlink
if (currentNode != null && CrossReferenceService.IsReferencedParaListItem)
{
bool FieldCountPresentAlready = false;
if (currentNode.ParentNode.Range.Fields.Count > 0)
{
FieldCountPresentAlready = true;
}
foreach (Field field in currentNode.ParentNode.Range.Fields)
{
if (field.Type == FieldType.FieldRef)
{
// Get the text from the field result
string resultText = field.Result;
// Remove the field from the document
field.Remove();
// Find the first paragraph after the parent node
Paragraph para = currentNode.ParentNode as Paragraph;
// If no paragraph found, create a new paragraph
if (para == null)
{
para = new Paragraph(currentNode.Document);
currentNode.ParentNode.ParentNode.InsertBefore(para, currentNode.ParentNode);
}
// Create a new Run node with the resultText
Run newRun = new Run(currentNode.Document, resultText);
para.InsertBefore(newRun, currentNode);
break;
}
}
if (FieldCountPresentAlready)
{
currentNode = currentNode.PreviousSibling;
if (currentNode.NodeType == NodeType.BookmarkEnd || currentNode.NodeType == NodeType.BookmarkStart)
{
currentNode = currentNode.PreviousSibling;
}
if (args.MatchOffset > 0 && currentNode.NextSibling.NodeType != NodeType.BookmarkStart && currentNode.NextSibling.NodeType != NodeType.BookmarkEnd)
{
currentNode = SplitRun((Aspose.Words.Run)currentNode, args.MatchOffset);
runs.Clear();
runs.Add((Aspose.Words.Run)currentNode);
}
else
{
runs.Clear();
runs.Add((Aspose.Words.Run)currentNode);
}
}
}
// Now Add field codes in the sequence
if (currentNode != null)
{
oDocBuild.MoveTo(currentNode);
}
else
{
oDocBuild.MoveTo(prevNodeVal);
}
SelectInsertReferenceType(oDocBuild, runs, currentNode);
foreach (Run run in runs)
{
if (run.ParentNode != null)
{
run.Remove();
}
}
}
catch (Exception ex)
{
ex.SplunkException();
}
return ReplaceAction.Skip;
}
private void SelectInsertReferenceType(DocumentBuilder oDocBuild, List<Run> runs, Node currentNode)
{
if (CrossReferenceService.IsReferencedParaListItem)
{
// Insert field after text
oDocBuild.MoveTo(runs[runs.Count - 1]);
oDocBuild.InsertField("REF _Ref" + mStartBookmarkNumber + " \\h", currentNode?.GetText());
// Remove text
runs.ForEach(r => r.Remove());
}
else
{
switch (CrossReferenceService.insertReferenceType)
{
case "page_number":
FieldPageRef ReffieldPage = (FieldPageRef)oDocBuild.InsertField(FieldType.FieldPageRef, false);
ReffieldPage.BookmarkName = "_Ref" + mStartBookmarkNumber;
ReffieldPage.InsertHyperlink = true;
ReffieldPage.Update();
break;
case "paragraph_number":
case "paragraph_number_no_context":
case "paragraph_number_full_context":
case "above_or_below":
case "paragraph_text":
FieldRef Reffield = (FieldRef)oDocBuild.InsertField(FieldType.FieldRef, false);
Reffield.InsertParagraphNumber = CrossReferenceService.insertReferenceType != "paragraph_text" && CrossReferenceService.insertReferenceType != "above_or_below";
if (CrossReferenceService.insertReferenceType == "paragraph_number_full_context")
{
Reffield.InsertParagraphNumberInFullContext = true;
}
else if (CrossReferenceService.insertReferenceType == "paragraph_number_no_context")
{
Reffield.InsertParagraphNumberInRelativeContext = true;
}
if (CrossReferenceService.insertReferenceType == "above_or_below")
{
Reffield.InsertRelativePosition = true;
}
Reffield.BookmarkName = "_Ref" + mStartBookmarkNumber;
Reffield.InsertHyperlink = true;
Reffield.Update();
break;
}
}
}
}
I have the above code, It creates the cross-reference link without any issues. I want to retain the source formatting while creating the cross reference links. How can I acheive this?