Usar expresiones regulares de C # para eliminar etiquetas HTML
139
¿Cómo uso la expresión regular de C # para reemplazar / eliminar todas las etiquetas HTML, incluidos los corchetes angulares? ¿Puede alguien ayudarme con el código?
No lo indica, pero infiero que también desea eliminar completamente los elementos de estilo y script y no solo eliminar la etiqueta. La respuesta de HTML Agility Pack a continuación es correcta para eliminar las etiquetas, pero para eliminar el script y el estilo, también necesitará algo como stackoverflow.com/questions/13441470/…
John
1
La pregunta indicada como duplicado tiene mucha información (¡y Tony el Pony!), Pero solo pedía abrir etiquetas, no todas las etiquetas. Así que no estoy seguro de que técnicamente sea un duplicado. Dicho esto, la respuesta es la misma: no lo hagas.
goodeye
Respuestas:
154
Como se indicó anteriormente, no debe usar expresiones regulares para procesar documentos XML o HTML. No funcionan muy bien con documentos HTML y XML, porque no hay forma de expresar estructuras anidadas de manera general.
Podrías usar lo siguiente.
String result =Regex.Replace(htmlDocument,@"<[^>]*>",String.Empty);
Esto funcionará para la mayoría de los casos, pero habrá casos (por ejemplo, CDATA que contienen paréntesis angulares) en los que esto no funcionará como se esperaba.
Esta es una implementación ingenua. Es decir, <div id = "x <4>"> es, desafortunadamente, html válido. Sin embargo
ocupa de la
8
Como se dijo, soy consciente de que esta expresión fallará en algunos casos. Ni siquiera estoy seguro de si el caso general puede ser manejado por cualquier expresión regular sin errores.
Daniel Brückner el
1
¡No, esto fallará en todos los casos! Es codicioso.
Jake
13
@Cipher, ¿por qué crees que la codicia es un problema? Suponiendo que la coincidencia comienza al comienzo de una etiqueta HTML válida, nunca se extenderá más allá del final de esa etiqueta. Para eso está el [^>].
Alan Moore el
1
@AlanMoore html no es un "lenguaje normal", es decir, no puede hacer coincidir correctamente todo lo que es html válido con expresiones regulares. ver: stackoverflow.com/questions/590747/…
Para robar descaradamente el comentario a continuación de jesse, y para evitar ser acusado de responder inadecuadamente la pregunta después de todo este tiempo, aquí hay un fragmento simple y confiable que usa el paquete de agilidad HTML que funciona incluso con los fragmentos de HTML caprichosos más imperfectamente formados:
HtmlDocument doc =newHtmlDocument();
doc.LoadHtml(Properties.Resources.HtmlContents);var text = doc.DocumentNode.SelectNodes("//body//text()").Select(node => node.InnerText);StringBuilder output =newStringBuilder();foreach(string line in text){
output.AppendLine(line);}string textOnly =HttpUtility.HtmlDecode(output.ToString());
Hay muy pocos casos defendibles para usar una expresión regular para analizar HTML, ya que HTML no se puede analizar correctamente sin una conciencia de contexto que es muy dolorosa de proporcionar incluso en un motor de expresiones regulares no tradicionales. Puede llegar hasta allí con un RegEx, pero deberá hacer verificaciones manuales.
Html Agility Pack puede proporcionarle una solución sólida que reducirá la necesidad de corregir manualmente las aberraciones que pueden resultar del tratamiento ingenuo de HTML como una gramática libre de contexto.
Una expresión regular puede obtener la mayoría de las veces lo que desea, pero fallará en casos muy comunes. Si puede encontrar un analizador mejor / más rápido que HTML Agility Pack, hágalo, pero no someta al mundo a hackers de HTML más rotos.
HTML Agility Pack no es la respuesta a todo lo relacionado con el trabajo con HTML (por ejemplo, ¿qué pasa si solo desea trabajar con fragmentos del código HTML?).
PropellerHead
77
Funciona bastante bien con fragmentos de HTML, y es la mejor opción para el escenario descrito por el póster original. Un Regex, por otro lado, solo funciona con un HTML idealizado y se romperá con un HTML perfectamente válido, porque la gramática del HTML no es regular. Si él estuviera usando Ruby, todavía habría sugerido nokogiri o hpricot, o beautifulsoup para Python. Es mejor tratar HTML como HTML, no un flujo de texto arbitrario sin gramática.
JasonTrue
1
HTML no es una gramática regular y, por lo tanto, no se puede analizar únicamente con expresiones regulares. Puede usar expresiones regulares para lexing, pero no para analizar. Es realmente así de simple. Los lingüistas habrían acordado esto incluso antes de que HTML existiera.
JasonTrue
20
Esto no es una cuestión de opinión. Una expresión regular puede obtener principalmente lo que desea la mayor parte del tiempo, pero fallará en casos muy comunes. Si puede encontrar un analizador mejor / más rápido que HTML Agility Pack, hágalo, pero no someta al mundo a hackers de HTML más rotos.
JasonTrue
2
No puede identificar correctamente las etiquetas HTML de manera confiable sin analizar HTML. ¿Entiendes toda la gramática para HTML? Vea el truco malvado para acercarse "bastante" que sugieren otras respuestas, y dígame por qué querría tener que mantener eso. Votándome en contra porque un intento rápido de hacky funciona para su entrada de muestra no va a hacer que su solución sea correcta. De vez en cuando he usado expresiones regulares para generar informes a partir de contenido HTML o para corregir alguna referencia de CSS utilizando coincidencias negativas en & gt; para limitar la posibilidad de errores, pero hicimos verificaciones adicionales; No fue un propósito general.
JasonTrue
38
La pregunta es demasiado amplia para ser respondida definitivamente. ¿Estás hablando de eliminar todas las etiquetas de un documento HTML del mundo real, como una página web? Si es así, tendrías que:
elimine la declaración <! DOCTYPE o <? xml prolog si existen
eliminar todos los comentarios de SGML
eliminar todo el elemento HEAD
eliminar todos los elementos SCRIPT y STYLE
hacer Grabthar-know-what con elementos FORM y TABLE
eliminar las etiquetas restantes
elimine las secuencias <! [CDATA [y]]> de las secciones CDATA pero deje solo su contenido
Eso está justo en la parte superior de mi cabeza: estoy seguro de que hay más. Una vez que hayas hecho todo eso, terminarás con palabras, oraciones y párrafos juntos en algunos lugares, y grandes pedazos de espacios en blanco inútiles en otros.
Pero, suponiendo que esté trabajando con solo un fragmento y pueda salirse con la simple eliminación de todas las etiquetas, aquí está la expresión regular que usaría:
Coincidir cadenas de comillas simples y dobles en sus propias alternativas es suficiente para tratar el problema de los corchetes angulares en los valores de los atributos. No veo ninguna necesidad de hacer coincidir explícitamente los nombres de los atributos y otras cosas dentro de la etiqueta, como lo hace la expresión regular en la respuesta de Ryan; La primera alternativa maneja todo eso.
En caso de que te estés preguntando acerca de esas (?>...)construcciones, son grupos atómicos . Hacen que la expresión regular sea un poco más eficiente, pero lo que es más importante, evitan el retroceso descontrolado, que es algo que siempre debes tener en cuenta cuando mezclas alternancia y cuantificadores anidados como lo he hecho. Realmente no creo que eso sea un problema aquí, pero sé que si no lo menciono, alguien más lo hará. ;-)
Esta expresión regular no es perfecta, por supuesto, pero probablemente sea tan buena como la que alguna vez necesitarás.
Esta es, de lejos, la mejor respuesta. Responde la pregunta del póster y explica por qué no se debe usar una expresión regular para la tarea dada. Bien hecho.
Si bien llego un poco tarde, me gustaría mencionar que esto también funciona en xml, como el producido por Word y otros productos de oficina. cualquiera que haya tenido la necesidad de lidiar con Word xml haría bien en ver el uso de esto porque ayuda mucho, especialmente si necesita quitar etiquetas del contenido, que es exactamente para lo que lo necesitaba.
Steve Pettifer
Cuando todo parecía fallar, este simple fragmento de código salvó el día. ¡Gracias!
Ted Krapf
13
Me gustaría hacer eco de la respuesta de Jason, aunque a veces es necesario analizar ingenuamente algunos HTML y extraer el contenido del texto.
Necesitaba hacer esto con un poco de HTML creado por un editor de texto enriquecido, siempre divertido y con juegos.
En este caso, es posible que deba eliminar el contenido de algunas etiquetas, así como solo las etiquetas mismas.
En mi caso y las etiquetas fueron arrojadas a esta mezcla. Alguien puede encontrar mi implementación (muy ligeramente) menos ingenua como un punto de partida útil.
/// <summary>/// Removes all html tags from string and leaves only plain text/// Removes content of <xml></xml> and <style></style> tags as aim to get text content not markup /meta data./// </summary>/// <param name="input"></param>/// <returns></returns>publicstaticstringHtmlStrip(thisstring input){
input =Regex.Replace(input,"<style>(.|\n)*?</style>",string.Empty);
input =Regex.Replace(input,@"<xml>(.|\n)*?</xml>",string.Empty);// remove all <xml></xml> tags and anything inbetween. returnRegex.Replace(input,@"<(.|\n)*?>",string.Empty);// remove any tags but not there content "<p>bob<span> johnson</span></p>" becomes "bob johnson"}
Además de los problemas obvios de salto de línea de plataforma cruzada, tener un cuantificador no greged es lento cuando el contenido está delimitado. Use cosas como <xml>.*(?!</xml>)</xml>con el RegexOptions.SingleLinemodificador para los dos primeros y <[^>]*>para el último. Los primeros también se pueden combinar mediante una alternancia capturada en el primer nombre de etiqueta y referencias posteriores a ella en la etiqueta de búsqueda negativa y final.
/// <summary>/// Remove HTML from string with Regex./// </summary>publicstaticstringStripTagsRegex(string source){returnRegex.Replace(source,"<.*?>",string.Empty);}/// <summary>/// Compiled regular expression for performance./// </summary>staticRegex _htmlRegex =newRegex("<.*?>",RegexOptions.Compiled);/// <summary>/// Remove HTML from string with compiled Regex./// </summary>publicstaticstringStripTagsRegexCompiled(string source){return _htmlRegex.Replace(source,string.Empty);}
Respuestas:
Como se indicó anteriormente, no debe usar expresiones regulares para procesar documentos XML o HTML. No funcionan muy bien con documentos HTML y XML, porque no hay forma de expresar estructuras anidadas de manera general.
Podrías usar lo siguiente.
Esto funcionará para la mayoría de los casos, pero habrá casos (por ejemplo, CDATA que contienen paréntesis angulares) en los que esto no funcionará como se esperaba.
fuente
La respuesta correcta es no hacer eso, use el paquete de agilidad HTML .
Editado para agregar:
Para robar descaradamente el comentario a continuación de jesse, y para evitar ser acusado de responder inadecuadamente la pregunta después de todo este tiempo, aquí hay un fragmento simple y confiable que usa el paquete de agilidad HTML que funciona incluso con los fragmentos de HTML caprichosos más imperfectamente formados:
Hay muy pocos casos defendibles para usar una expresión regular para analizar HTML, ya que HTML no se puede analizar correctamente sin una conciencia de contexto que es muy dolorosa de proporcionar incluso en un motor de expresiones regulares no tradicionales. Puede llegar hasta allí con un RegEx, pero deberá hacer verificaciones manuales.
Html Agility Pack puede proporcionarle una solución sólida que reducirá la necesidad de corregir manualmente las aberraciones que pueden resultar del tratamiento ingenuo de HTML como una gramática libre de contexto.
Una expresión regular puede obtener la mayoría de las veces lo que desea, pero fallará en casos muy comunes. Si puede encontrar un analizador mejor / más rápido que HTML Agility Pack, hágalo, pero no someta al mundo a hackers de HTML más rotos.
fuente
La pregunta es demasiado amplia para ser respondida definitivamente. ¿Estás hablando de eliminar todas las etiquetas de un documento HTML del mundo real, como una página web? Si es así, tendrías que:
Eso está justo en la parte superior de mi cabeza: estoy seguro de que hay más. Una vez que hayas hecho todo eso, terminarás con palabras, oraciones y párrafos juntos en algunos lugares, y grandes pedazos de espacios en blanco inútiles en otros.
Pero, suponiendo que esté trabajando con solo un fragmento y pueda salirse con la simple eliminación de todas las etiquetas, aquí está la expresión regular que usaría:
Coincidir cadenas de comillas simples y dobles en sus propias alternativas es suficiente para tratar el problema de los corchetes angulares en los valores de los atributos. No veo ninguna necesidad de hacer coincidir explícitamente los nombres de los atributos y otras cosas dentro de la etiqueta, como lo hace la expresión regular en la respuesta de Ryan; La primera alternativa maneja todo eso.
En caso de que te estés preguntando acerca de esas
(?>...)
construcciones, son grupos atómicos . Hacen que la expresión regular sea un poco más eficiente, pero lo que es más importante, evitan el retroceso descontrolado, que es algo que siempre debes tener en cuenta cuando mezclas alternancia y cuantificadores anidados como lo he hecho. Realmente no creo que eso sea un problema aquí, pero sé que si no lo menciono, alguien más lo hará. ;-)Esta expresión regular no es perfecta, por supuesto, pero probablemente sea tan buena como la que alguna vez necesitarás.
fuente
Fuente
fuente
@JasonTrue es correcto, que la eliminación de etiquetas HTML no debe hacerse a través de expresiones regulares.
Es bastante simple quitar las etiquetas HTML usando HtmlAgilityPack:
fuente
Me gustaría hacer eco de la respuesta de Jason, aunque a veces es necesario analizar ingenuamente algunos HTML y extraer el contenido del texto.
Necesitaba hacer esto con un poco de HTML creado por un editor de texto enriquecido, siempre divertido y con juegos.
En este caso, es posible que deba eliminar el contenido de algunas etiquetas, así como solo las etiquetas mismas.
En mi caso y las etiquetas fueron arrojadas a esta mezcla. Alguien puede encontrar mi implementación (muy ligeramente) menos ingenua como un punto de partida útil.
fuente
<xml>.*(?!</xml>)</xml>
con elRegexOptions.SingleLine
modificador para los dos primeros y<[^>]*>
para el último. Los primeros también se pueden combinar mediante una alternancia capturada en el primer nombre de etiqueta y referencias posteriores a ella en la etiqueta de búsqueda negativa y final.pruebe el método de expresión regular en esta URL: http://www.dotnetperls.com/remove-html-tags
fuente
utilizar este..
fuente
Añadir
.+?
en<[^>]*>
y tratar esta expresión regular (base en esto ):Demo de expresiones regulares c # .net
fuente
Use este método para eliminar etiquetas:
fuente