Estoy tratando de reemplazar esta horrible colección de expresiones regulares que actualmente se usa para limpiar bloques de HTML mal formado y tropecé con el paquete de agilidad HTML para C #. Se ve muy poderoso pero, sin embargo, no pude encontrar un ejemplo de cómo quiero usar el paquete que, en mi opinión, sería una funcionalidad deseada incluida en él. Estoy seguro de que soy un idiota y no puedo encontrar un método adecuado en la documentación.
Déjame explicarte ... digamos que tenía el siguiente html:
<p class="someclass">
<font size="3">
<font face="Times New Roman">
this is some text
<a href="somepage.html">Some link</a>
</font>
</font>
</p>
... que me quiero ver así:
<p>
this is some text
<a href="somepage.html">Some link</a>
</p>
Cuando utilizo el método HtmlNode.Remove (), elimina el nodo más todos sus hijos. ¿Hay alguna manera de eliminar el nodo preservando a los niños?
En HtmlNode, el método RemoveChild tiene esta sobrecarga:
public HtmlNode RemoveChild(HtmlNode oldChild, bool keepGrandChildren);
Así es como lo harías:
HtmlDocument doc = new HtmlDocument();
doc.Load("yourfile.htm");
foreach (HtmlNode font in doc.DocumentNode.SelectNodes("//font"))
{
font.ParentNode.RemoveChild(font, true);
}
EDITAR: Parece que la opción Reemplazar con keepGrandChildren no funciona como se esperaba, así que aquí hay una implementación alternativa:
public static HtmlNode RemoveChild(HtmlNode parent, HtmlNode oldChild, bool keepGrandChildren)
{
if (oldChild == null)
throw new ArgumentNullException("oldChild");
if (oldChild.HasChildNodes && keepGrandChildren)
{
HtmlNode prev = oldChild.PreviousSibling;
List<HtmlNode> nodes = new List<HtmlNode>(oldChild.ChildNodes.Cast<HtmlNode>());
nodes.Sort(new StreamPositionComparer());
foreach (HtmlNode grandchild in nodes)
{
parent.InsertAfter(grandchild, prev);
}
}
parent.RemoveChild(oldChild);
return oldChild;
}
// this helper class allows to sort nodes using their position in the file.
private class StreamPositionComparer : IComparer<HtmlNode>
{
int IComparer<HtmlNode>.Compare(HtmlNode x, HtmlNode y)
{
return y.StreamPosition.CompareTo(x.StreamPosition);
}
}
Puede intentar usar AngleSharp en su lugar.
var parser = new HtmlParser();
var document = parser.Parse(html);
using (var writer = new StringWriter())
{
document.ToHtml(writer, new PrettyMarkupFormatter());
return writer.ToString();
}