How do I use HTML Agility Pack to edit an HTML snippet

c# html-agility-pack

Question

So I have an HTML snippet that I want to modify using C#.

<div>
This is a specialSearchWord that I want to link to
<img src="anImage.jpg" />
<a href="foo.htm">A hyperlink</a>
Some more text and that specialSearchWord again.
</div>

and I want to transform it to this:

<div>
This is a <a class="special" href="http://mysite.com/search/specialSearchWord">specialSearchWord</a> that I want to link to
<img src="anImage.jpg" />
<a href="foo.htm">A hyperlink</a>
Some more text and that <a class="special" href="http://mysite.com/search/specialSearchWord">specialSearchWord</a> again.
</div>

I'm going to use HTML Agility Pack based on the many recommendations here, but I don't know where I'm going. In particular,

  1. How do I load a partial snippet as a string, instead of a full HTML document?
  2. How do edit?
  3. How do I then return the text string of the edited object?

Accepted Answer

  1. The same as a full HTML document. It doesn't matter.
  2. The are 2 options: you may edit InnerHtml property directly (or Text on text nodes) or modifying the dom tree by using e.g. AppendChild, PrependChild etc.
  3. You may use HtmlDocument.DocumentNode.OuterHtml property or use HtmlDocument.Save method (personally I prefer the second option).

As to parsing, I select the text nodes which contain the search term inside your div, and then just use string.Replace method to replace it:

var doc = new HtmlDocument();
doc.LoadHtml(html);
var textNodes = doc.DocumentNode.SelectNodes("/div/text()[contains(.,'specialSearchWord')]");
if (textNodes != null)
    foreach (HtmlTextNode node in textNodes)
        node.Text = node.Text.Replace("specialSearchWord", "<a class='special' href='http://mysite.com/search/specialSearchWord'>specialSearchWord</a>");

And saving the result to a string:

string result = null;
using (StringWriter writer = new StringWriter())
{
    doc.Save(writer);
    result = writer.ToString();
}

Popular Answer

Answers:

  1. There may be a way to do this but I don't know how. I suggest loading the entire document.
  2. Use a combination of XPath and regular expressions
  3. See the code below for a contrived example. You may have other constraints not mentioned but this code sample should get you started.

Note that your Xpath expression may need to be more complex to find the div that you want.

HtmlDocument doc = new HtmlDocument();

doc.Load(yourHtmlFile);
HtmlNode divNode = doc.DocumentNode.SelectSingleNode("//div[2]");
string newDiv = Regex.Replace(divNode.InnerHtml, @"specialSearchWord", 
"<a class='special' href='http://etc'>specialSearchWord</a>");
divNode.InnerHtml = newDiv;
Console.WriteLine(doc.DocumentNode.OuterHtml);



Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Is this KB legal? Yes, learn why
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Is this KB legal? Yes, learn why