#c# #html-agility-pack
#c# #html-agility-pack
Вопрос:
Допустим, я хочу удалить тег span из этого html:
<html><span>we do like <b>bold</b> stuff</span></html>
Я ожидаю, что этот фрагмент кода будет делать то, что мне нужно
string html = "<html><span>we do like <b>bold</b> stuff</span></html>";
HtmlDocument doc = new HtmlDocument();
doc.LoadHtml(html);
HtmlNode span = doc.DocumentNode.Descendants("span").First();
span.ParentNode.RemoveChild(span, true); //second parameter is 'keepGrandChildren'
Но результат выглядит так:
<html> stuff<b>bold</b>we do like </html>
Похоже, что он меняет дочерние узлы в пределах диапазона. Я делаю что-то не так?
Ответ №1:
Похоже на ошибку в HtmlAgilityPack — см. Их реестр проблем:
http://htmlagilitypack.codeplex.com/workitem/9113
Интересно, что это было поднято 4 года назад…
Вот фрагмент, который удалит все теги span (или любой другой указанный вами тег) и сохранит другие узлы в правильном порядке.
void Main()
{
string html = "<html><span>we do like <b>bold</b> stuff</span></html>";
HtmlDocument doc = new HtmlDocument();
doc.LoadHtml(html);
RemoveTags(doc, "span");
Console.WriteLine(doc.DocumentNode.OuterHtml);
}
public static void RemoveTags(HtmlDocument html, string tagName)
{
var tags = html.DocumentNode.SelectNodes("//" tagName);
if (tags!=null)
{
foreach (var tag in tags)
{
if (!tag.HasChildNodes)
{
tag.ParentNode.RemoveChild(tag);
continue;
}
for (var i = tag.ChildNodes.Count - 1; i >= 0; i--)
{
var child = tag.ChildNodes[i];
tag.ParentNode.InsertAfter(child, tag);
}
tag.ParentNode.RemoveChild(tag);
}
}
}
Комментарии:
1. Интересно, что это все еще происходит в 2017 году
2. …и в 2019 году. Спасибо за отличное предложение и код. Отлично работает!
Ответ №2:
foreach (HtmlNode child in tag.ChildNodes)
{
tag.ParentNode.InsertBefore(child, tag);
}
tag.Remove();
Ответ №3:
Просто для записи, это моя версия, основанная на ответах на этот вопрос:
using HtmlAgilityPack;
internal static class HtmlAgilityPackExtensions
{
public static void RemoveNodeKeepChildren(this HtmlNode node)
{
foreach (var child in node.ChildNodes)
{
node.ParentNode.InsertBefore(child, node);
}
node.Remove();
}
}