If you plan on doing this on the server, you should use the line builder. The reason is that memory performance will be HORRENDOUS if you use strings. Effectively every time you remove a tag from your string, you actually copy the string. For each recursion (tag), your system will do this, so if you even have a reasonable size of HTML input, you use a huge amount of memory very quickly.
EDIT: Regarding Chris's comment, this previous statement is true if you are dealing with large lines. If you parse small chunks of HTML using a line builder, this is not so important. But I made the assumption that you are using this on a server in a web environment, so you can consume very large pages with it.
Using a string builder as a reference will also allow your function to manipulate the mutable value, so at the end of your recursion, StringBuilder.ToString () will correctly output your mutated string.
You should migrate others who mentioned row volatility as your problem, if you enhance my solution, please :).
I tried to answer your problem and fix the next one, which believes that this is a mistake that many have made before.
Also note that your code will die on <br/>
private static string FixHtml(StringBuilder bldr) { if (String.Compare(blder.ToString(0,5), "<div>", true) == 0) { blder.remove(0, 5); return FixHtml(blder); } else if (String.Compare(blder.ToString(0,3), "<p>", true) == 0) { blder.remove(0, 3); return FixHtml(blder); } else if (String.Compare(blder.ToString(bldr.Length - 6, 6), "</div>", true) == 0) { blder.remove(blder.Length - 6, 6); return FixHtml(blder); } else if (String.Compare(blder.ToString(bldr.Length - 4, 4), "</p>", true) == 0) { blder.remove(blder.Length - 4, 4); return FixHtml(blder); } return blder.ToString(); }