2009-04-17 14 views
9

Al utilizar HTMLAgilityPack para escribir un nuevo nodo de imagen, parece eliminar la etiqueta de cierre de una imagen, p. debería ser, pero cuando revisas html externo, tiene.Etiqueta de imagen que no se cierra con HTMLAgilityPack

string strIMG = "<img src='" + imgPath + "' height='" + pubImg.Height + "px' width='" + pubImg.Width + "px' />"; 

HtmlNode newNode = HtmlNode.Create(strIMG); 

Esto rompe xhtml.

Respuesta

2

Hay una opción para activar la salida XML que hace que este problema desaparezca.

var htmlDoc = new HtmlDocument(); 
htmlDoc.OptionOutputAsXml = true; 
htmlDoc.LoadHtml(rawHtml); 
+2

un problema con este método es que las entidades previamente codificadas, como un espacio sin frenos, se codifica, esto puede ser un comportamiento no deseado – MJJames

19

diciéndole que se XML de salida como Micky sugiere obras, pero si usted tiene otras razones para no querer XML, intente esto:

doc.OptionWriteEmptyNodes = true; 
1

Esto parece ser un error con HtmlAgilityPack. Hay muchas maneras de reproducir esto, por ejemplo:

Debug.WriteLine(HtmlNode.CreateNode("<img id=\"bla\"></img>").OuterHtml); 

salidas HTML con formato incorrecto. Usar las correcciones sugeridas en las otras respuestas no hace nada.

HtmlDocument doc = new HtmlDocument(); 
doc.OptionOutputAsXml = true; 
HtmlNode node = doc.CreateElement("x"); 
node.InnerHtml = "<img id=\"bla\"></img>"; 
doc.DocumentNode.AppendChild(node); 
Debug.WriteLine(doc.DocumentNode.OuterHtml); 

Produce mal formado XML/XHTML como <x><img id="bla"></x>

I have created a issue in CodePlex for this.

+1

El hecho de que este problema aún existe y que hay problemas en el rastreador desde el 2007 y una cantidad considerable a partir de 2010 no me quedaría boquiabierto si esto se solucionara pronto. – Nenotlep

+0

Recomiendo HAP para el análisis pero no para modificar el HTML existente. –

2

Edición 1: Aquí es cómo solucionar un documento HTML Agilty paquete para visualizar correctamente imágenes (IMG) tags:

if (HtmlNode.ElementsFlags.ContainsKey("img")) 
{ HtmlNode.ElementsFlags["img"] = HtmlElementFlag.Closed;} 
else 
{ HtmlNode.ElementsFlags.Add("img", HtmlElementFlag.Closed);} 

reemplace "img" para que cualquier otra etiqueta también las corrija (las entradas, selecciones y opciones aparecen con frecuencia). Repita según sea necesario. Tenga en cuenta que esto producirá en lugar de, debido a la falla HAP que impide que las banderas "cerrada" y "vacía" se configuren simultáneamente. Fuente: MikeBridge en http://htmlagilitypack.codeplex.com/discussions/53782

Respuesta original: Habiendo trabajó sobre las soluciones a este problema, y ​​no encontrar ninguna respuesta suficientes (tipo de documento ajustado correctamente, utilizando la salida como XML, Revisar sintaxis, AutoCloseOnEnd, y suscribir opciones nodo vacío) Pude resolver esto con un truco sucio. Esto definitivamente no resolverá el problema directamente para todos, pero para cualquiera que devuelva su html/xml generado como una cadena (EG a través de un servicio web), la solución simple es usar etiquetas falsas que el paquete de agilidad no sabe para romper . Una vez que haya terminado de hacer todo lo que necesita hacer en su documento, llame al siguiente método una vez para cada etiqueta que le da un dolor de cabeza (ejemplos notables son opción, entrada e img). Inmediatamente después, renderice la cadena final y realice una sustitución simple para cada etiqueta con el prefijo de una cadena (en este caso, "Fix_") y devuelva la cadena. Esto es apenas un poco mejor en mi opinión, que la solución de expresiones regulares se propone en otra pregunta que no puede localizar en el momento (algo en la línea de)

private void fixHAPUnclosedTags(ref HtmlDocument doc, string tagName, bool hasInnerText = false) 
{ 
    HtmlNode tagReplacement = null; 
    foreach(var tag in doc.DocumentNode.SelectNodes("//"+tagName) 
    { 
     tagReplacement = HtmlTextNode.CreateNode("<fix_"+tagName+"></fix_"+tagName+">"); 
     foreach(var attr in tag.Attributes) 
     { 
      tagReplacement.SetAttributeValue(attr.Name, attr.Value); 
     } 
     if(hasInnerText)//for option tags and other non-empty nodes, the next (text) node will be its inner HTML 
     { 
      tagReplacement.InnerHtml = tag.InnerHtml + tag.NextSibling.InnerHtml; 
      tag.NextSibling.Remove(); 
     } 
     tag.ParentNode.ReplaceChild(tagReplacement, tag); 
    } 
} 

Como nota, si yo fuera un hombre de apuestas Conjeturaría que la respuesta de MikeBridge inadvertidamente identifica el origen de este error en el paquete - algo está causando que las banderas cerradas y vacías sean mutuamente excluyentes

Además, después de un poco más de excavación, no parezco ser el único que ha adoptado este enfoque:

Además, en casos en los que SÓLO necesita elementos no vacíos, hay una solución muy simple en la misma pregunta, así como la discusión codeplex de HAP aquí: http://htmlagilitypack.codeplex.com/discussions/14982?ProjectName=htmlagilitypack Esto esencialmente establece la opción de indicador vacío en la respuesta de MikeBridge arriba permanentemente en todas partes.

Cuestiones relacionadas