Пакет гибкости HTML - удаление ненужных тегов без удаления содержимого?
Я видел несколько связанных вопросов здесь, но они на самом деле не говорят о той же проблеме, с которой я столкнулся.
Я хочу использовать HTML Agility Pack для удаления ненужных тегов из моего HTML без потери содержимого в тегах.
Так, например, в моем сценарии я хотел бы сохранить теги "b
", "i
" и "u
".
И для ввода типа:
<p>my paragraph <div>and my <b>div</b></div> are <i>italic</i> and <b>bold</b></p>
В результате HTML должен выглядеть так:
my paragraph and my <b>div</b> are <i>italic</i> and <b>bold</b>
Я попытался использовать метод HtmlNode
Remove
, но он также удаляет мой контент. Любые предложения?
Ответы
Ответ 1
Я написал алгоритм, основанный на предложениях Одеда. Вот. Работает как шарм.
Он удаляет все теги, кроме strong
, em
, u
и узлов исходного текста.
internal static string RemoveUnwantedTags(string data)
{
if(string.IsNullOrEmpty(data)) return string.Empty;
var document = new HtmlDocument();
document.LoadHtml(data);
var acceptableTags = new String[] { "strong", "em", "u"};
var nodes = new Queue<HtmlNode>(document.DocumentNode.SelectNodes("./*|./text()"));
while(nodes.Count > 0)
{
var node = nodes.Dequeue();
var parentNode = node.ParentNode;
if(!acceptableTags.Contains(node.Name) && node.Name != "#text")
{
var childNodes = node.SelectNodes("./*|./text()");
if (childNodes != null)
{
foreach (var child in childNodes)
{
nodes.Enqueue(child);
parentNode.InsertBefore(child, node);
}
}
parentNode.RemoveChild(node);
}
}
return document.DocumentNode.InnerHtml;
}
Ответ 2
Как рекурсивно удалить заданный список нежелательных тегов html из строки html
Я принял @mathias ответ и улучшил его метод расширения, чтобы вы могли предоставить список тегов для исключения в качестве List<string>
(например, {"a","p","hr"}
). Я также исправил логику так, чтобы она работала рекурсивно правильно:
public static string RemoveUnwantedHtmlTags(this string html, List<string> unwantedTags)
{
if (String.IsNullOrEmpty(html))
{
return html;
}
var document = new HtmlDocument();
document.LoadHtml(html);
HtmlNodeCollection tryGetNodes = document.DocumentNode.SelectNodes("./*|./text()");
if (tryGetNodes == null || !tryGetNodes.Any())
{
return html;
}
var nodes = new Queue<HtmlNode>(tryGetNodes);
while (nodes.Count > 0)
{
var node = nodes.Dequeue();
var parentNode = node.ParentNode;
var childNodes = node.SelectNodes("./*|./text()");
if (childNodes != null)
{
foreach (var child in childNodes)
{
nodes.Enqueue(child);
}
}
if (unwantedTags.Any(tag => tag == node.Name))
{
if (childNodes != null)
{
foreach (var child in childNodes)
{
parentNode.InsertBefore(child, node);
}
}
parentNode.RemoveChild(node);
}
}
return document.DocumentNode.InnerHtml;
}
Ответ 3
Попробуйте следующее: вы можете найти его немного опережающим, чем другие предлагаемые решения:
public static int RemoveNodesButKeepChildren(this HtmlNode rootNode, string xPath)
{
HtmlNodeCollection nodes = rootNode.SelectNodes(xPath);
if (nodes == null)
return 0;
foreach (HtmlNode node in nodes)
node.RemoveButKeepChildren();
return nodes.Count;
}
public static void RemoveButKeepChildren(this HtmlNode node)
{
foreach (HtmlNode child in node.ChildNodes)
node.ParentNode.InsertBefore(child, node);
node.Remove();
}
public static bool TestYourSpecificExample()
{
string html = "<p>my paragraph <div>and my <b>div</b></div> are <i>italic</i> and <b>bold</b></p>";
HtmlDocument document = new HtmlDocument();
document.LoadHtml(html);
document.DocumentNode.RemoveNodesButKeepChildren("//div");
document.DocumentNode.RemoveNodesButKeepChildren("//p");
return document.DocumentNode.InnerHtml == "my paragraph and my <b>div</b> are <i>italic</i> and <b>bold</b>";
}
Ответ 4
Прежде чем удалить node, выберите его родительский элемент и его InnerText
, затем удалите node и повторно назначьте InnerText
родительскому элементу.
var parent = node.ParentNode;
var innerText = parent.InnerText;
node.Remove();
parent.AppendChild(doc.CreateTextNode(innerText));
Ответ 5
Если вы не хотите использовать пакет гибкости Html и все еще хотите удалить ненужный тег HTML, чем вы можете сделать, как показано ниже.
public static string RemoveHtmlTags(string strHtml)
{
string strText = Regex.Replace(strHtml, "<(.|\n)*?>", String.Empty);
strText = HttpUtility.HtmlDecode(strText);
strText = Regex.Replace(strText, @"\s+", " ");
return strText;
}