Pregunta

¿Existe una buena manera de eliminar HTML de una cadena de Java?Una expresión regular simple como

 replaceAll("\\<.*?>","") 

funcionará, pero cosas como &amp; no se convertirá correctamente y se eliminará el formato no HTML entre los dos corchetes angulares (es decir,el .*? en la expresión regular desaparecerá).

¿Fue útil?

Solución

Utilice un analizador HTML en lugar de expresiones regulares.Esto es muy simple con sopa.

public static String html2text(String html) {
    return Jsoup.parse(html).text();
}

Jsoup también apoya eliminar etiquetas HTML de una lista blanca personalizable, lo cual es muy útil si desea permitir solo, p. <b>, <i> y <u>.

Ver también:

Otros consejos

Si estás escribiendo para Android puedes hacer esto ...

android.text.Html.fromHtml(instruction).toString()

Si el usuario ingresa <b>hey!</b>, ¿desea mostrar hey! o <bhey!</b>? Si es el primero, escape menos-thans y html-codifique símbolos (y opcionalmente comillas) y estará bien. Una modificación a su código para implementar la segunda opción sería:

replaceAll("\\<[^>]*>","")

pero se encontrará con problemas si el usuario ingresa algo mal formado, como <=>.

También puede consultar JTidy que analizará " dirty " html input, y debería darle una forma de eliminar las etiquetas, manteniendo el texto.

El problema al intentar eliminar html es que los navegadores tienen analizadores muy indulgentes, más indulgentes que cualquier biblioteca que pueda encontrar, por lo que incluso si hace todo lo posible para eliminar todas las etiquetas (utilizando el método de reemplazo anterior, una biblioteca DOM, o JTidy), aún deberá asegurarse de codificar los caracteres especiales HTML restantes para mantener su salida segura.

Otra forma es usar javax.swing.text.html.HTMLEditorKit para extraer el texto.

import java.io.*;
import javax.swing.text.html.*;
import javax.swing.text.html.parser.*;

public class Html2Text extends HTMLEditorKit.ParserCallback {
    StringBuffer s;

    public Html2Text() {
    }

    public void parse(Reader in) throws IOException {
        s = new StringBuffer();
        ParserDelegator delegator = new ParserDelegator();
        // the third parameter is TRUE to ignore charset directive
        delegator.parse(in, this, Boolean.TRUE);
    }

    public void handleText(char[] text, int pos) {
        s.append(text);
    }

    public String getText() {
        return s.toString();
    }

    public static void main(String[] args) {
        try {
            // the HTML to convert
            FileReader in = new FileReader("java-new.html");
            Html2Text parser = new Html2Text();
            parser.parse(in);
            in.close();
            System.out.println(parser.getText());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

ref: Elimine las etiquetas HTML de un archivo para extraer solo el TEXTO

Creo que la forma más sencilla de filtrar las etiquetas html es:

private static final Pattern REMOVE_TAGS = Pattern.compile("<.+?>");

public static String removeTags(String string) {
    if (string == null || string.length() == 0) {
        return string;
    }

    Matcher m = REMOVE_TAGS.matcher(string);
    return m.replaceAll("");
}

También es muy simple usando Jericho , y puede conservar parte del formato (línea saltos y enlaces, por ejemplo).

    Source htmlSource = new Source(htmlText);
    Segment htmlSeg = new Segment(htmlSource, 0, htmlSource.length());
    Renderer htmlRend = new Renderer(htmlSeg);
    System.out.println(htmlRend.toString());

En Android, intente esto:

String result = Html.fromHtml(html).toString();

HTML Escaping es realmente difícil de hacer bien, definitivamente sugeriría usar el código de la biblioteca para hacer esto, ya que es mucho más sutil de lo que piensas. Eche un vistazo a StringEscapeUtils de Apache para una biblioteca bastante buena para manejar esto en Java.

La respuesta aceptada de hacer simplemente Jsoup.parse(html).text() tiene 2 problemas potenciales (con JSoup 1.7.3):

  • Elimina los saltos de línea del texto
  • Convierte el texto &lt;script&gt; en <script>

Si usa esto para protegerse contra XSS, esto es un poco molesto. Aquí está mi mejor oportunidad de obtener una solución mejorada, utilizando JSoup y Apache StringEscapeUtils:

// breaks multi-level of escaping, preventing &amp;lt;script&amp;gt; to be rendered as <script>
String replace = input.replace("&amp;", "");
// decode any encoded html, preventing &lt;script&gt; to be rendered as <script>
String html = StringEscapeUtils.unescapeHtml(replace);
// remove all html tags, but maintain line breaks
String clean = Jsoup.clean(html, "", Whitelist.none(), new Document.OutputSettings().prettyPrint(false));
// decode html again to convert character entities back into text
return StringEscapeUtils.unescapeHtml(clean);

Tenga en cuenta que el último paso es porque necesito usar la salida como texto sin formato. Si solo necesita salida HTML, entonces debería poder eliminarla.

Y aquí hay un montón de casos de prueba (entrada a salida):

{"regular string", "regular string"},
{"<a href=\"link\">A link</a>", "A link"},
{"<script src=\"http://evil.url.com\"/>", ""},
{"&lt;script&gt;", ""},
{"&amp;lt;script&amp;gt;", "lt;scriptgt;"}, // best effort
{"\" ' > < \n \\ é å à ü and & preserved", "\" ' > < \n \\ é å à ü and & preserved"}

Si encuentra una manera de mejorarlo, avíseme.

Es posible que desee reemplazar <br/> y </p> etiquetas con nuevas líneas antes de eliminar el HTML para evitar que se convierta en un desastre ilegible como sugiere Tim.

La única forma en que se me ocurre eliminar etiquetas HTML pero dejar etiquetas que no sean HTML entre corchetes angulares sería compararlas con una lista de etiquetas HTML.Algo parecido a esto...

replaceAll("\\<[\s]*tag[^>]*>","")

Luego, decodifica HTML con caracteres especiales como &amp;.El resultado no debe considerarse desinfectado.

Esto debería funcionar -

usa esto

  text.replaceAll('<.*?>' , " ") -> This will replace all the html tags with a space.

y esto

  text.replaceAll('&.*?;' , "")-> this will replace all the tags which starts with "&" and ends with ";" like &nbsp;, &amp;, &gt; etc.

La respuesta aceptada no funcionó para mí para el caso de prueba que indiqué: el resultado de " a < b o b > c " es " a b o b > c " ;.

Entonces, usé TagSoup en su lugar. Aquí hay una foto que funcionó para mi caso de prueba (y un par de otros):

import java.io.IOException;
import java.io.StringReader;
import java.util.logging.Logger;

import org.ccil.cowan.tagsoup.Parser;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.InputSource;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;

/**
 * Take HTML and give back the text part while dropping the HTML tags.
 *
 * There is some risk that using TagSoup means we'll permute non-HTML text.
 * However, it seems to work the best so far in test cases.
 *
 * @author dan
 * @see <a href="http://home.ccil.org/~cowan/XML/tagsoup/">TagSoup</a> 
 */
public class Html2Text2 implements ContentHandler {
private StringBuffer sb;

public Html2Text2() {
}

public void parse(String str) throws IOException, SAXException {
    XMLReader reader = new Parser();
    reader.setContentHandler(this);
    sb = new StringBuffer();
    reader.parse(new InputSource(new StringReader(str)));
}

public String getText() {
    return sb.toString();
}

@Override
public void characters(char[] ch, int start, int length)
    throws SAXException {
    for (int idx = 0; idx < length; idx++) {
    sb.append(ch[idx+start]);
    }
}

@Override
public void ignorableWhitespace(char[] ch, int start, int length)
    throws SAXException {
    sb.append(ch);
}

// The methods below do not contribute to the text
@Override
public void endDocument() throws SAXException {
}

@Override
public void endElement(String uri, String localName, String qName)
    throws SAXException {
}

@Override
public void endPrefixMapping(String prefix) throws SAXException {
}


@Override
public void processingInstruction(String target, String data)
    throws SAXException {
}

@Override
public void setDocumentLocator(Locator locator) {
}

@Override
public void skippedEntity(String name) throws SAXException {
}

@Override
public void startDocument() throws SAXException {
}

@Override
public void startElement(String uri, String localName, String qName,
    Attributes atts) throws SAXException {
}

@Override
public void startPrefixMapping(String prefix, String uri)
    throws SAXException {
}
}

Sé que esto es antiguo, pero solo estaba trabajando en un proyecto que me requería filtrar HTML y funcionó bien:

noHTMLString.replaceAll("\\&.*?\\;", "");

en lugar de esto:

html = html.replaceAll("&nbsp;","");
html = html.replaceAll("&amp;"."");

Aquí hay una actualización un poco más detallada para tratar de manejar algunos formatos para saltos y listas. Usé la salida de Amaya como guía.

import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.util.Stack;
import java.util.logging.Logger;

import javax.swing.text.MutableAttributeSet;
import javax.swing.text.html.HTML;
import javax.swing.text.html.HTMLEditorKit;
import javax.swing.text.html.parser.ParserDelegator;

public class HTML2Text extends HTMLEditorKit.ParserCallback {
    private static final Logger log = Logger
            .getLogger(Logger.GLOBAL_LOGGER_NAME);

    private StringBuffer stringBuffer;

    private Stack<IndexType> indentStack;

    public static class IndexType {
        public String type;
        public int counter; // used for ordered lists

        public IndexType(String type) {
            this.type = type;
            counter = 0;
        }
    }

    public HTML2Text() {
        stringBuffer = new StringBuffer();
        indentStack = new Stack<IndexType>();
    }

    public static String convert(String html) {
        HTML2Text parser = new HTML2Text();
        Reader in = new StringReader(html);
        try {
            // the HTML to convert
            parser.parse(in);
        } catch (Exception e) {
            log.severe(e.getMessage());
        } finally {
            try {
                in.close();
            } catch (IOException ioe) {
                // this should never happen
            }
        }
        return parser.getText();
    }

    public void parse(Reader in) throws IOException {
        ParserDelegator delegator = new ParserDelegator();
        // the third parameter is TRUE to ignore charset directive
        delegator.parse(in, this, Boolean.TRUE);
    }

    public void handleStartTag(HTML.Tag t, MutableAttributeSet a, int pos) {
        log.info("StartTag:" + t.toString());
        if (t.toString().equals("p")) {
            if (stringBuffer.length() > 0
                    && !stringBuffer.substring(stringBuffer.length() - 1)
                            .equals("\n")) {
                newLine();
            }
            newLine();
        } else if (t.toString().equals("ol")) {
            indentStack.push(new IndexType("ol"));
            newLine();
        } else if (t.toString().equals("ul")) {
            indentStack.push(new IndexType("ul"));
            newLine();
        } else if (t.toString().equals("li")) {
            IndexType parent = indentStack.peek();
            if (parent.type.equals("ol")) {
                String numberString = "" + (++parent.counter) + ".";
                stringBuffer.append(numberString);
                for (int i = 0; i < (4 - numberString.length()); i++) {
                    stringBuffer.append(" ");
                }
            } else {
                stringBuffer.append("*   ");
            }
            indentStack.push(new IndexType("li"));
        } else if (t.toString().equals("dl")) {
            newLine();
        } else if (t.toString().equals("dt")) {
            newLine();
        } else if (t.toString().equals("dd")) {
            indentStack.push(new IndexType("dd"));
            newLine();
        }
    }

    private void newLine() {
        stringBuffer.append("\n");
        for (int i = 0; i < indentStack.size(); i++) {
            stringBuffer.append("    ");
        }
    }

    public void handleEndTag(HTML.Tag t, int pos) {
        log.info("EndTag:" + t.toString());
        if (t.toString().equals("p")) {
            newLine();
        } else if (t.toString().equals("ol")) {
            indentStack.pop();
            ;
            newLine();
        } else if (t.toString().equals("ul")) {
            indentStack.pop();
            ;
            newLine();
        } else if (t.toString().equals("li")) {
            indentStack.pop();
            ;
            newLine();
        } else if (t.toString().equals("dd")) {
            indentStack.pop();
            ;
        }
    }

    public void handleSimpleTag(HTML.Tag t, MutableAttributeSet a, int pos) {
        log.info("SimpleTag:" + t.toString());
        if (t.toString().equals("br")) {
            newLine();
        }
    }

    public void handleText(char[] text, int pos) {
        log.info("Text:" + new String(text));
        stringBuffer.append(text);
    }

    public String getText() {
        return stringBuffer.toString();
    }

    public static void main(String args[]) {
        String html = "<html><body><p>paragraph at start</p>hello<br />What is happening?<p>this is a<br />mutiline paragraph</p><ol>  <li>This</li>  <li>is</li>  <li>an</li>  <li>ordered</li>  <li>list    <p>with</p>    <ul>      <li>another</li>      <li>list        <dl>          <dt>This</dt>          <dt>is</dt>            <dd>sdasd</dd>            <dd>sdasda</dd>            <dd>asda              <p>aasdas</p>            </dd>            <dd>sdada</dd>          <dt>fsdfsdfsd</dt>        </dl>        <dl>          <dt>vbcvcvbcvb</dt>          <dt>cvbcvbc</dt>            <dd>vbcbcvbcvb</dd>          <dt>cvbcv</dt>          <dt></dt>        </dl>        <dl>          <dt></dt>        </dl></li>      <li>cool</li>    </ul>    <p>stuff</p>  </li>  <li>cool</li></ol><p></p></body></html>";
        System.out.println(convert(html));
    }
}

Alternativamente, uno puede usar HtmlCleaner :

private CharSequence removeHtmlFrom(String html) {
    return new HtmlCleaner().clean(html).getText();
}

Use Html.fromHtml

HTML Las etiquetas son

<a href=”…”> <b>,  <big>, <blockquote>, <br>, <cite>, <dfn>
<div align=”…”>,  <em>, <font size=”…” color=”…” face=”…”>
<h1>,  <h2>, <h3>, <h4>,  <h5>, <h6>
<i>, <p>, <small>
<strike>,  <strong>, <sub>, <sup>, <tt>, <u>

Según Android & # 8217; s Documentaciones oficiales cualquier etiqueta en el HTML se mostrará como un reemplazo genérico de String que su programa puede revisar y reemplazar con cadenas .

El método

Html.formHtml toma un Html.TagHandler y un Html.ImageGetter como argumentos, así como el texto para analizar.

Ejemplo

String Str_Html=" <p>This is about me text that the user can put into their profile</p> ";

Entonces

Your_TextView_Obj.setText(Html.fromHtml(Str_Html).toString());

Salida

Esto es sobre mí texto que el usuario puede poner en su perfil

Una forma más puede ser usar la clase com.google.gdata.util.common.html.HtmlToText me gusta

MyWriter.toConsole(HtmlToText.htmlToPlainText(htmlResponse));

Sin embargo, este no es un código a prueba de balas y cuando lo ejecuto en las entradas de wikipedia también obtengo información de estilo. Sin embargo, creo que para trabajos pequeños / simples esto sería efectivo.

Parece que quiere pasar de HTML a texto sin formato.
Si ese es el caso, visite www.htmlparser.org. Aquí hay un ejemplo que elimina todas las etiquetas del archivo html que se encuentra en una URL.
Utiliza org.htmlparser.beans.StringBean .

static public String getUrlContentsAsText(String url) {
    String content = "";
    StringBean stringBean = new StringBean();
    stringBean.setURL(url);
    content = stringBean.getStrings();
    return content;
}

Aquí hay otra forma de hacerlo:

public static String removeHTML(String input) {
    int i = 0;
    String[] str = input.split("");

    String s = "";
    boolean inTag = false;

    for (i = input.indexOf("<"); i < input.indexOf(">"); i++) {
        inTag = true;
    }
    if (!inTag) {
        for (i = 0; i < str.length; i++) {
            s = s + str[i];
        }
    }
    return s;
}

Aquí hay una variante más de cómo reemplazar todo (Etiquetas HTML | Entidades HTML | Espacio vacío en contenido HTML)

content.replaceAll("(<.*?>)|(&.*?;)|([ ]{2,})", ""); donde el contenido es una Cadena.

También se podría usar Apache Tika para este propósito. De forma predeterminada, conserva espacios en blanco del HTML despojado, que puede desearse en ciertas situaciones:

InputStream htmlInputStream = ..
HtmlParser htmlParser = new HtmlParser();
HtmlContentHandler htmlContentHandler = new HtmlContentHandler();
htmlParser.parse(htmlInputStream, htmlContentHandler, new Metadata())
System.out.println(htmlContentHandler.getBodyText().trim())

Una forma de retener información de nueva línea con JSoup es preceder todas las nuevas etiquetas de línea con alguna cadena ficticia, ejecutar JSoup y reemplazar la cadena ficticia con " \ n " ;.

String html = "<p>Line one</p><p>Line two</p>Line three<br/>etc.";
String NEW_LINE_MARK = "NEWLINESTART1234567890NEWLINEEND";
for (String tag: new String[]{"</p>","<br/>","</h1>","</h2>","</h3>","</h4>","</h5>","</h6>","</li>"}) {
    html = html.replace(tag, NEW_LINE_MARK+tag);
}

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

text = text.replace(NEW_LINE_MARK + " ", "\n\n");
text = text.replace(NEW_LINE_MARK, "\n\n");

Simplemente puede usar el filtro HTML predeterminado de Android

    public String htmlToStringFilter(String textToFilter){

    return Html.fromHtml(textToFilter).toString();

    }

El método anterior devolverá la cadena filtrada de HTML para su entrada.

Mis 5 centavos:

String[] temp = yourString.split("&amp;");
String tmp = "";
if (temp.length > 1) {

    for (int i = 0; i < temp.length; i++) {
        tmp += temp[i] + "&";
    }
    yourString = tmp.substring(0, tmp.length() - 1);
}

Para obtener texto HTML plano con formato puede hacer eso:

String BR_ESCAPED = "&lt;br/&gt;";
Element el=Jsoup.parse(html).select("body");
el.select("br").append(BR_ESCAPED);
el.select("p").append(BR_ESCAPED+BR_ESCAPED);
el.select("h1").append(BR_ESCAPED+BR_ESCAPED);
el.select("h2").append(BR_ESCAPED+BR_ESCAPED);
el.select("h3").append(BR_ESCAPED+BR_ESCAPED);
el.select("h4").append(BR_ESCAPED+BR_ESCAPED);
el.select("h5").append(BR_ESCAPED+BR_ESCAPED);
String nodeValue=el.text();
nodeValue=nodeValue.replaceAll(BR_ESCAPED, "<br/>");
nodeValue=nodeValue.replaceAll("(\\s*<br[^>]*>){3,}", "<br/><br/>");

Para obtener texto plano formateado cambie < br / > por \ ny cambiar la última línea por:

nodeValue=nodeValue.replaceAll("(\\s*\n){3,}", "<br/><br/>");
classeString.replaceAll("\\<(/?[^\\>]+)\\>", "\\ ").replaceAll("\\s+", " ").trim() 

simplemente puede hacer un método con múltiples replaceAll () como

String RemoveTag(String html){
   html = html.replaceAll("\\<.*?>","")
   html = html.replaceAll("&nbsp;","");
   html = html.replaceAll("&amp;"."");
   ----------
   ----------
   return html;
}

Use este enlace para los reemplazos más comunes que necesita: http://tunes.org/wiki/html_20special_20characters_20and_20symbols.html

Es simple pero efectivo. Primero uso este método para eliminar la basura, pero no la primera línea, es decir, reemplazarAll (& Quot; \ & Lt;. *? & Gt; & Quot;, & Quot; quot;), y luego uso palabras clave específicas para buscar índices y luego uso el método .substring (inicio, fin) para eliminar cosas innecesarias. Como esto es más robusto y puede señalar exactamente lo que necesita en toda la página html.

Eliminar etiquetas HTML de la cadena. En algún lugar necesitamos analizar alguna cadena que es recibida por algunas respuestas como Httpresponse del servidor.

Por lo tanto, debemos analizarlo.

Aquí mostraré cómo eliminar etiquetas html de la cadena.

    // sample text with tags

    string str = "<html><head>sdfkashf sdf</head><body>sdfasdf</body></html>";



    // regex which match tags

    System.Text.RegularExpressions.Regex rx = new System.Text.RegularExpressions.Regex("<[^>]*>");



    // replace all matches with empty strin

    str = rx.Replace(str, "");



    //now str contains string without html tags
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top