HtmlAgilityPack set node InnerText

Try code below. It select all nodes without children and filtered out script nodes. Maybe you need to add some additional filtering. In addition to your XPath expression this one also looking for leaf nodes and filter out text content of <script> tags.

var nodes = doc.DocumentNode.SelectNodes("//body//text()[(normalize-space(.) != '') and not(parent::script) and not(*)]");
foreach (HtmlNode htmlNode in nodes)
{
    htmlNode.ParentNode.ReplaceChild(HtmlTextNode.CreateNode(htmlNode.InnerText + "_translated"), htmlNode);
}

Strange, but I found that InnerHtml isn't readonly. And when I tried to set it like that

aElement.InnerHtml = "sometext";

the value of InnerText also changed to "sometext"


The HtmlTextNode class has a Text property* which works perfectly for this purpose.

Here's an example:

var textNodes = doc.DocumentNode.SelectNodes("//body/text()").Cast<HtmlTextNode>();
foreach (var node in textNodes)
{
    node.Text = node.Text.Replace("foo", "bar");
}

And if we have an HtmlNode that we want to change its direct text, we can do something like the following:

HtmlNode node = //...
var textNode = (HtmlTextNode)node.SelectSingleNode("text()");
textNode.Text = "new text";

Or we can use node.SelectNodes("text()") in case it has more than one.


*Not to be confused with the readonly InnerText property.