We have an issue with inserting RTF formatted text into placeholders in another RTF document (a placeholder will typically be some text in the form [[placeholder-name]]), and we are considering whether Aspose.Words might be able to solve this issue.
Our current solution plainly find the placeholder and replaces it with the formatted text, directly in the RTF file, without considering any formatting incompatibilities there might be. This works okay, but have a few quirks.
Our issue arises when the rtf we are inserting, contains plain paragraphs (\pard\plain…\par) but the placeholder we are replacing is contained within a table (thus a surrounding paragraph will have the form \pard\intbl…\par). This leads to a quite weird looking document - which was not intended.
I have found this article describing a way to use Aspose.Words to copy content between paragraphs - but how does it handle these kinds of situations where the source and target have different surroundings and thus require different styles for their paragraphs?
Our product contains a templating engine which is based on RTF, and we would like to replace our old simple rtf-parser which has no idea of the actual properties of rtf (only understands the syntax), with some other module that has better understanding on RTF and will allow us to do these kinds of placeholder-replacements, with better results in terms of less style violations.
Best regards,
Michael Dahl
Ditmer A/S
Hi Michael,
Thanks for your inquiry. In your case, we suggest you following solution.
- Implement IReplacingCallback interface to find the placeholder’s text.
- Load the RTF into new Document inside IReplacingCallback.Replacing.
- Move the cursor to the placeholder’s text and insert the new RTF document using DocumentBuilder.InsertDocument method.
Please read following documentation link and check following code example for your kind reference. Hope this helps you.
Find and Replace
class FindandInsertDocument : IReplacingCallback
{
private String path;
public FindandInsertDocument(String documentpath)
{
path = documentpath;
}
///
/// This method is called by the Aspose.Words find and replace engine for each match.
///
ReplaceAction IReplacingCallback.Replacing(ReplacingArgs e)
{
// This is a Run node that contains either the beginning or the complete match.
Node currentNode = e.MatchNode;
// 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 (e.MatchOffset > 0)
currentNode = SplitRun((Run)currentNode, e.MatchOffset);
// This array is used to store all nodes of the match for further removing.
ArrayList runs = new ArrayList();
// Find all runs that contain parts of the match string.
int remainingLength = e.Match.Value.Length;
while (
(remainingLength > 0) &&
(currentNode != null) &&
(currentNode.GetText().Length <= remainingLength))
{
runs.Add(currentNode);
remainingLength = remainingLength - currentNode.GetText().Length;
// 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((Run)currentNode, remainingLength);
runs.Add(currentNode);
}
// Create Document Builder and insert RTF document
DocumentBuilder builder = new DocumentBuilder(e.MatchNode.Document as Document);
builder.MoveTo((Run)runs[runs.Count - 1]);
Document doc = new Document(path);
builder.InsertDocument(doc, ImportFormatMode.KeepSourceFormatting);
// Now remove all runs in the sequence.
foreach (Run run in runs)
run.Remove();
// Signal to the replace engine to do nothing because we have already done all what we wanted.
return ReplaceAction.Skip;
}
private static Run SplitRun(Run run, int position)
{
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;
}
}
Document mainDoc = new Document(MyDir + "in.rtf");
mainDoc.Range.Replace(new Regex("\\[MY_DOCUMENT\\]"), new FindandInsertDocument(MyDir + "new rtf document.rtf"), false);
mainDoc.Save(MyDir + "Out.rtf");
Hi Tahir,
Thank you for replying so quickly.
It sounds very promising - I have attached your comments to our internal issue, so that we hopefully soon will be able to address our issue using Aspose.Words as our new templating engine.
Best regards,
Michael Dahl
Hi Michael,
Please feel free to ask if you have any question about Aspose.Words, we will be happy to help you.