2009-05-07 38 views
37

¿Existe una biblioteca Java existente que proporcione un método para quitar todas las etiquetas HTML de una cadena? Estoy buscando algo equivalente a la función strip_tags en PHP.Eliminación de etiquetas HTML en Java

Sé que puedo usar una expresión regular como se describe en this Stackoverflow question, sin embargo, estaba ansioso por ver si puede haber ya un método stripTags() flotando en algún lugar en la biblioteca de Apache Commons que se puede utilizar.

+3

Mientras tanto estoy usando el siguiente código para quitar todas las etiquetas HTML de la cadena: cadena strippedHtml = rawHtml.replaceAll ("<(.|\n)*?>", ""); – Todd

Respuesta

10

Después de tener esta pregunta abierta durante casi una semana, puedo decir con cierta certeza de que no hay un método disponible en la API de Java o libaries Apache que elimina las etiquetas HTML de una cadena. Tendría que usar un analizador HTML como se describe en las respuestas anteriores, o escribir una expresión regular simple para quitar las etiquetas.

+0

Um, ¿qué crees que haría una cosa así, si no es un analizador HTML?O, para el caso, ¿qué te imaginas que estás haciendo con una expresión regular? –

+0

Lo que imagino que está haciendo con una expresión regular es lo mismo que estoy haciendo con una expresión regular: eliminar cualquier cosa de una cadena que parece que podría ser una etiqueta HTML para garantizar que la cadena resultante sea ambas (1) legible por humanos y (2) no causa una vulnerabilidad XSS si está incrustado en una página web. – Jules

11

Puede haber algunas, pero la más robusta es usar un analizador de HTML real. Hay uno here, y si está razonablemente bien formado, también puede usar SAX u otro analizador XML.

+0

Por supuesto, si lo que estás buscando para salir al final es una cadena que está garantizado seguro para incluir en la salida HTML, un analizador de HTML no es lo que usted quiere, si la cadena '< script de alerta > ('hola'); ' se pasará por el analizador sintáctico y terminará siendo peligroso aunque no sea para empezar ... – Jules

+0

Ahora ve a ver qué hace un analizador HTML, hay un buen chico. –

+0

Quizás si pudieras dejar de ser condescendiente, sería más útil. Estoy bastante familiarizado con los analizadores de HTML, y he usado muchos en los últimos 20 años. Por lo general, la salida de un analizador HTML sería un DOM o algo similar, pero claramente la pregunta pedido una cadena, por lo que estoy asumiendo su sugerencia sería utilizar la propiedad W3C DOM 'textContent' del DOM analizada resultante, o algo equivalente si usa un analizador cuya salida no es un DOM. Si esto es lo que está recomendando, esto es peligroso porque permitirá a través de contenido HTML si está codificado en el documento de origen como entidades. – Jules

6

He usado nekoHtml para hacer eso. Puede quitar todas las etiquetas, pero también puede mantener o quitar un subconjunto de etiquetas.

25

Hagas lo que hagas, asegúrate de normalizar los datos antes de comenzar a tratar de quitar las etiquetas. Recientemente asistí a un taller de seguridad de aplicaciones web que cubría la evasión de filtros XSS. Uno normalmente pensaría que la búsqueda de < o &lt; o su equivalente hexadecimal sería suficiente. Me quedé impresionado después de ver una diapositiva con 70 formas en que < se puede codificar para vencer a los filtros.

Actualización:

A continuación se muestra la presentación que me refería, véase la diapositiva 26 para las 70 formas de codificar <.

Filter Evasion: Houdini on the Wire

+0

¿Podría agregar un enlace a esa diapositiva? Creo que no hay tantos métodos de codificación válidos para el navegador ... –

+0

buena lectura. . Gracias por compartir – Jianhong

+0

corrígeme si me equivoco, pero ¿no es el primer elemento en esta lista, el único que en realidad será interpretado por un navegador como iniciar una etiqueta HTML? El resto se mostrará tal cual o se mostrará como un literal '<' en el documento resultante, ¿no es cierto? Si es así, ¿cuál es exactamente el objetivo de esta lista? – Jules

0

Wicket utiliza el siguiente método para escapar html, ubicado en: org.apache.wicket.util.string.Strings

public static CharSequence escapeMarkup(final String s, final boolean escapeSpaces, 
    final boolean convertToHtmlUnicodeEscapes) 
{ 
    if (s == null) 
    { 
     return null; 
    } 
    else 
    { 
     int len = s.length(); 
     final AppendingStringBuffer buffer = new AppendingStringBuffer((int)(len * 1.1)); 

     for (int i = 0; i < len; i++) 
     { 
      final char c = s.charAt(i); 

      switch (c) 
      { 
       case '\t' : 
        if (escapeSpaces) 
        { 
         // Assumption is four space tabs (sorry, but that's 
         // just how it is!) 
         buffer.append("&nbsp;&nbsp;&nbsp;&nbsp;"); 
        } 
        else 
        { 
         buffer.append(c); 
        } 
        break; 

       case ' ' : 
        if (escapeSpaces) 
        { 
         buffer.append("&nbsp;"); 
        } 
        else 
        { 
         buffer.append(c); 
        } 
        break; 

       case '<' : 
        buffer.append("&lt;"); 
        break; 

       case '>' : 
        buffer.append("&gt;"); 
        break; 

       case '&' : 

        buffer.append("&amp;"); 
        break; 

       case '"' : 
        buffer.append("&quot;"); 
        break; 

       case '\'' : 
        buffer.append("&#039;"); 
        break; 

       default : 

        if (convertToHtmlUnicodeEscapes) 
        { 
         int ci = 0xffff & c; 
         if (ci < 160) 
         { 
          // nothing special only 7 Bit 
          buffer.append(c); 
         } 
         else 
         { 
          // Not 7 Bit use the unicode system 
          buffer.append("&#"); 
          buffer.append(new Integer(ci).toString()); 
          buffer.append(';'); 
         } 
        } 
        else 
        { 
         buffer.append(c); 
        } 

        break; 
      } 
     } 

     return buffer; 
    } 
} 
+2

Esto se está escapando, no eliminando – gregers

+0

¡Exactamente, hay una diferencia entre esos dos! – Rihards

27

Esto es lo que encontré en Google en él. Para mí funcionó bien.

String noHTMLString = htmlString.replaceAll("\\<.*?\\>", ""); 
+2

¿Esto no eliminará etiquetas que no sean html como ? – Abhilash

+2

No creo que una expresión regular corta como esta _pueda cubrir todos los casos de html ... ¿qué hay sobre el formato especial? buenas bibliotecas como JSoup incluso se preocupan por formatear cuando generan texto sin formato (!) ... quiero decir, transformación, nunca lo conseguirás solo con regex – jebbie

+0

Quizás algún código pueda leer y usar una DTD válida –

2

Hola Sé que este hilo es viejo pero todavía salió tapas en Google, y yo estaba buscando una solución rápida para el mismo problema. No pude encontrar nada útil, así que se me ocurrió este fragmento de código. Espero que ayude a alguien. Simplemente pasa por encima de la cadena y se salta todas las etiquetas. Simple & simple.

boolean intag = false; 
String inp = "<H1>Some <b>HTML</b> <span style=blablabla>text</span>"; 
String outp = ""; 

for (int i=0; i < inp.length(); ++i) 
{ 
    if (!intag && inp.charAt(i) == '<') 
     { 
      intag = true; 
      continue; 
     } 
     if (intag && inp.charAt(i) == '>') 
     { 
      intag = false; 
      continue; 
     } 
     if (!intag) 
     { 
      outp = outp + inp.charAt(i); 
     } 
} 
return outp; 
+0

Usted podría considerar usar StringBuilder para su salida. ¿Cómo manejarías HTML malformado? ¿Qué sucede si mi HTML contiene caracteres menores o menores que los que no tiene escapadas? – allingeek

31

Uso JSoup, está bien documentado, disponible en Maven y después de un día de pasar tiempo con varias bibliotecas, para mí, es el mejor que puedo imaginar .. Mi opinión es que un trabajo como que, analizando html en texto plano, debería ser posible en una línea de código -> de lo contrario, la biblioteca ha fallado de alguna manera ... simplemente diciendo ^^ Así que aquí está, el one-liner de JSoup - en Markdown4J, algo así no es posible, en Markdownj también, en htmlCleaner este es el dolor en el culo con un tanto cerca de 50 líneas de código ...

String plain = new HtmlToPlainText().getPlainText(Jsoup.parse(html)); 

Y lo que tienes es de texto plano real (no solo html-source-code como String, como en otras libs lol) -> realmente hace un gran trabajo al respecto.Es más o menos la misma calidad que Markdownify para PHP ....

+0

El problema con Jsoup es que también elimina nuevas líneas, por lo que toda la entrada analizada estará en una sola línea. – johnflan

+0

Y que el resultado puede contener etiquetas HTML si la entrada contiene "% gt; tag <" o similar. – Jules

+0

ok, pero Jules pero no es un problema de JSoup ... ¿hay otros mejores en eso? no importa, porque me parece mejor que simplemente decodifique la cadena html codificada en la url antes de darle a JSoup en lugar de escribir varias líneas de código de hundert para lograr lo que JSoup hace (si otra lib aquí sería mejor en ese cosa particular) – jebbie

4

Sé que esta pregunta es bastante antigua, pero he estado buscando esto también y parece que todavía no es fácil encontrar una buena y una solución fácil en java.

Hoy me encontré con este pequeño funciones lib. En realidad, intenta imitar la función php strip_tags.

http://jmelo.lyncode.com/java-strip_tags-php-function/

Funciona de la siguiente (copiado de su sitio):

import static com.lyncode.jtwig.functions.util.HtmlUtils.stripTags; 

    public class StripTagsExample { 
     public static void main(String... args) { 
     String result = stripTags("<!-- <a href='test'></a>--><a>Test</a>", ""); 
     // Produced result: Test 
     } 
    } 
2

Con enfoque iterativo pura y sin expresiones regulares:

public String stripTags(final String html) { 

    final StringBuilder sbText = new StringBuilder(); 
    final StringBuilder sbHtml = new StringBuilder(); 

    boolean isText = true; 

    for (char ch : html.toCharArray()) { 
     if (isText) { // outside html 
      if (ch != '<') { 
       sbText.append(ch); 
       continue; 
      } else { // switch mode    
       isText = false;  
       sbHtml.append(ch); 
       continue; 
      } 
     }else { // inside html 
      if (ch != '>') { 
       sbHtml.append(ch); 
       continue; 
      } else {  // switch mode  
       isText = true;  
       sbHtml.append(ch); 
       continue; 
      } 
     } 
    } 

    return sbText.toString(); 
} 
5

Al utilizar Jsoup es aún más fácil de lo descrito en respuestas anteriores:

String html = "bla <b>hehe</b> <br> this is awesome simple"; 

String text = Jsoup.parse(html).text(); 
+0

Esto funcionó para mí y parecía no plantear ningún problema con la conversión de espacios de Jsoup a nuevas líneas ('TextNode' que contiene solo espacio) o nuevas líneas a espacios (comportamiento Jsoup normal), que parecían ser problemas con' new HtmlToPlainText() .getPlainText (Jsoup.parse (htmlHitLine)); ' –

+0

Me alegra oír eso :)) –

0
public static String stripTags(String str) { 
    int startPosition = str.indexOf('<'); 
    int endPosition; 
    while (startPosition != -1) { 
     endPosition = str.indexOf('>', startPosition); 
     str = str.substring(0, startPosition) + (endPosition != -1 ? str.substring(endPosition + 1) : ""); 
     startPosition = str.indexOf('<'); 
    } 
    return str; 
} 
0

Tuve también el problema de una cadena truncada que daba como resultado etiquetas html no cerradas que regex no puede detectar. ES:

Lorem ipsum dolor sit amet, <b>consectetur</b> adipiscing elit. <a href="abc" 

Así, refiriéndose a los 2 mejores respuestas (JSoup y expresiones regulares), yo prefería solución utilizando JSoup:

Jsoup.parse(html).text()