Hello,
I have a requirement to get a list of Nodes which match the given text.
For example in the Aspose.Words DOM, there is a Run with text = “added with track changes”;
I tried the following options but they are not returning a match:
a) builder.Document.SelectNodes("//Run[@Text=‘added with track changes’]")
b) builder.Document.SelectNodes("//Run[Text=‘added with track changes’]")
Can you please let me know how to get such a list by Text value?
Thank you.
Hi there,
Thanks for your inquiry. Please note that all text of the document is stored in runs of text. The text “added with track changes” in the document may or may not be in a single Run node. It is possible that this text is in multiple Run node.
You can achieve your requirement by implementing IReplacingCallback interface as shown in following code example. Please use the same approach shared at following documentation link to find and replace specific text.
Document doc = new Document(MyDir + "in.docx");
Regex regex = new Regex("your text", RegexOptions.IgnoreCase);
FindMatchedNodes obj = new FindMatchedNodes();
doc.Range.Replace(regex, obj, true);
foreach (Node node in obj.nodes)
{
//Your code
}
public class FindMatchedNodes : IReplacingCallback
{
//Store Matched nodes in ArrayList
public ArrayList nodes = new ArrayList();
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);
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);
}
String runText = "";
foreach (Run run in runs)
runText += run.Text;
((Run)runs[0]).Text = runText;
for (int i = 1; i < runs.Count; i++)
{
((Run)runs[i]).Remove();
}
nodes.Add(runs[0]);
// Signal to the replace engine to do nothing because we have already done all what we wanted.
return ReplaceAction.Skip;
}
}