Удалить теги HTML из строки

Есть ли хороший способ удалить HTML из строки Java? Простое регулярное выражение вроде

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

будет работать, но такие вещи, как &amp;, не будут преобразованы правильно, а не-HTML между двумя угловыми скобками будет удален (то есть .*? в регулярном выражении исчезнет).

используйте это со следующим руководством: скомпилируйте 'org.jsoup: jsoup: 1.9.2'

VahidHoseini 26.09.2016 22:01
stackoverflow.com/a/3149645/5733853
VahidHoseini 26.09.2016 22:02

См. Также: stackoverflow.com/a/21838532/363573

Stephan 18.01.2019 18:11
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
439
3
486 697
34
Перейти к ответу Данный вопрос помечен как решенный

Ответы 34

Если пользователь вводит <b>hey!</b>, вы хотите отобразить <b>hey!</b> или hey!? Если первое, избегайте less-thans и html-кодируйте амперсанды (и, возможно, кавычки), и все в порядке. Модификация вашего кода для реализации второго варианта будет следующей:

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

но вы столкнетесь с проблемами, если пользователь введет что-то некорректное, например <bhey!</b>.

Вы также можете проверить JTidy, который будет анализировать «грязный» ввод html и должен дать вам способ удалить теги, сохранив текст.

Проблема с попыткой удалить html заключается в том, что браузеры имеют очень мягкие парсеры, более мягкие, чем любая библиотека, которую вы можете найти, поэтому, даже если вы сделаете все возможное, чтобы удалить все теги (используя метод замены выше, библиотеку DOM или JTidy) , вам понадобится по-прежнему, чтобы убедиться, что вы закодировали все оставшиеся специальные символы HTML, чтобы ваш вывод был безопасным.

Вы также столкнетесь с проблемами, если внутри содержимого узла html есть неэкранированный знак <или>. <span> Мой возраст <много текста> вашего возраста </span>. Я думаю, что только 100% способ сделать это - через некоторый интерфейс XML DOM (например, SAX или аналогичный), чтобы использовать node.getText ().

Mitja Gustin 24.10.2017 16:14

Экранирование HTML действительно сложно сделать правильно - я бы определенно предложил использовать для этого библиотечный код, поскольку он намного более тонкий, чем вы думаете. Ознакомьтесь с Apache StringEscapeUtils, чтобы найти довольно хорошую библиотеку для обработки этого на Java.

Это то, что я ищу, но я хочу удалить HTML, а не экранировать его.

Mason 27.10.2008 20:12

вы хотите удалить HTML или преобразовать его в обычный текст? Удаление HTML из длинной строки с тегами br и объектами HTML может привести к неразборчивому беспорядку.

Tim Howland 27.10.2008 20:52

Вы пробовали StringEscapeUtils.unescapeHtml? с общего языка?

Rafael Sanches 16.02.2012 22:32

StringEscapeUtils.unescapeHtml не удаляет HTML

Erin Drummond 16.08.2012 07:04

Хорошая информация об утилитах, которые можно использовать для отмены экранирования, но не для ответа на вопрос.

Alex 18.06.2014 09:33

Непонятный ответ. Удаление! = Неэкранирование

Lluis Martinez 28.10.2014 17:41

Возможно, вы захотите заменить теги <br/> и </p> на новые строки перед удалением HTML, чтобы он не превратился в неразборчивый беспорядок, как предлагает Тим.

Единственный способ, которым я могу думать об удалении HTML-тегов, но оставив не-HTML между угловыми скобками, - это проверить на список HTML-тегов. Что-то в этом роде ...

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

Затем декодируйте специальные символы HTML, такие как &amp;. Результат не следует считать дезинфицированным.

Похоже, вы хотите перейти от HTML к обычному тексту. Если это так, загляните на сайт www.htmlparser.org. Вот пример, который удаляет все теги из HTML-файла, найденного по URL-адресу. Он использует org.htmlparser.beans.StringBean.

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

Другой способ - использовать javax.swing.text.html.HTMLEditorKit для извлечения текста.

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();
        }
    }
}

ссылка: Удалите HTML-теги из файла, чтобы извлечь только ТЕКСТ

Результатом «a <b or b> c» будет «a b or b> c», что кажется неудачным.

dfrankow 13.08.2010 02:56

Это сработало для меня лучше всего. Мне нужно было сохранить разрывы строк. Я сделал это, добавив в парсер этот простой метод: @Override public void handleStartTag (HTML.Tag t, MutableAttributeSet a, int pos) {if (t == HTML.Tag.P || t == HTML.Tag.BR) {s.append ('\ п'); }}

MiguelMunoz 19.02.2020 00:06

dfrankow: Математическое выражение a <b или b> c должно быть записано в html следующим образом: a & lt; b или b & gt; c

MiguelMunoz 19.02.2020 00:18

Мне нравится, что у этого нет внешних зависимостей.

Matthieu 09.07.2020 16:32

Вот немного более подробное обновление, чтобы попытаться обработать некоторое форматирование разрывов и списков. Я использовал вывод Amaya в качестве руководства.

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));
    }
}
Ответ принят как подходящий

Используйте парсер HTML вместо регулярного выражения. Это очень просто с Jsoup.

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

Jsoup также поддерживает удаляет HTML-теги из настраиваемого белого списка, что очень полезно, если вы хотите разрешить только, например, <b>, <i> и <u>.

Смотрите также:

Jsoup хорош, но я столкнулся с некоторыми недостатками. Я использую его, чтобы избавиться от XSS, поэтому в основном я ожидаю ввода простого текста, но какой-то злой человек может попытаться отправить мне немного HTML. Используя Jsoup, я могу удалить весь HTML, но, к сожалению, он также сжимает много пробелов до одного и удаляет разрывы ссылок (\ n символов)

Ridcully 31.07.2010 13:57

@Ridcully: для этого вы хотите использовать вместо этого Jsoup#clean().

BalusC 06.08.2010 22:24

использование clean () по-прежнему приведет к удалению лишних пробелов и \ n символов. пример: Jsoup.clean ("a \ n b", Whitelist.none ()) возвращает "a b"

Keith 02.05.2011 02:15

@Keith: конечно, лишние пробелы и \ n будут удалены, поскольку HTML игнорирует их, и вы вызываете .clean ()

Eduardo 20.07.2011 01:53

Будет ли это выполнять также «побег атрибутов»? Я специально имею в виду Правило №2 в этом списке: owasp.org/index.php/…

Nels Beckman 24.10.2011 20:41

@Nels: ты про Jsoup#clean()? Да, безусловно. Щелкните ссылку «Jsoup # clean ()» в моем предыдущем комментарии.

BalusC 24.10.2011 20:45

Увы, убраны новые строчки. А они нам нужны :)

Bozho 31.05.2012 10:44

input.replaceAll ("<[^>] *>", "");

Aalkhodiry 05.03.2013 18:22

@Zeroows: это ужасно не работает на <p>Lorem ipsum 1 < 3 dolor sit amet</p>. Опять же, HTML не является обычным языком. Мне совершенно непонятно, почему все продолжают пытаться использовать регулярное выражение для анализа интересующих частей вместо того, чтобы использовать настоящий синтаксический анализатор.

BalusC 05.03.2013 18:24

Ваше мыло сэкономило мне несколько часов сна :) Какая отличная реализация!

Uri Lukach 02.02.2014 03:04

Я также нашел этот ответ неудовлетворительным для XSS, и я опубликовал еще один ответ.

Damien 13.05.2014 08:21

Это НАМНОГО лучше, чем Html.fromHtml

Lisa Anne 15.02.2015 11:49

используйте Jsoup.clean(unsafeString, "", Whitelist.none(), new OutputSettings().prettyPrint(false)); для сохранения переносов строк

Marc Johnen 16.08.2016 13:19

скомпилируйте это: compile 'org.jsoup: jsoup: 1.9.2'

VahidHoseini 26.09.2016 22:00

Это может быть лучше, но это приводит к другой зависимости вашего проекта, что не очень хорошо.

RexSplode 14.05.2018 17:39

Не работал с вводимым текстом: «Привет, <span>! Пожалуйста, не используйте <и>»

Sindhu Venkatachary 27.08.2018 12:45

Может ли кто-нибудь объяснить, что делает это лучше, чем Html.fromHtml (..). ToString ()?

FrankKrumnow 25.11.2020 13:40

@FrankKrumnow: Html.fromHtml(..).toString() недоступен ни в стандартной Java, ни в стандартной библиотеке Java. Это доступно только в Android.

BalusC 25.11.2020 14:35

Виноват. Видел вопрос в контексте Android.

FrankKrumnow 26.11.2020 14:52

Я только что понял, что этот ответ подразумевает строку HTML. А если мы говорим об общей строке? Т.е. нет возможности отключить экранирование lt, gt, amp, quot. Если строка содержит &, JSoup очистит ее как & amp. (пытался использовать его для очистки строки JSON, чтобы предотвратить XSS)

jalmasi 08.03.2021 21:20

@jalmasi: просто просмотрите JSON и очистите каждое строковое свойство, а не весь объект JSON. Или, если ваш парсер JSON поддерживает это, зарегистрируйте новый слушатель / адаптер / somethingTheyCallIt, чтобы ваш парсер JSON делал это автоматически.

BalusC 08.03.2021 21:24

@BalusC это именно то, что я делаю - jackson, de / serializer for by type. Но очиститель Jsoup заменяет gt, lt, amp, quot, несмотря ни на что, и отключить это невозможно. Т.е. нет EscapeMode.none :)

jalmasi 09.03.2021 22:53

Еще один способ - использовать класс com.google.gdata.util.common.html.HtmlToText. нравиться

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

Это не пуленепробиваемый код, и когда я запускаю его в записях википедии, я также получаю информацию о стиле. Однако я считаю, что для небольших / простых работ это было бы эффективно.

Принятый ответ не сработал для указанного мной тестового примера: результат «a <b or b> c» равен «a b or b> c».

Поэтому вместо этого я использовал TagSoup. Вот снимок, который сработал для моего тестового примера (и нескольких других):

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 {
}
}

Я думаю, что самый простой способ отфильтровать теги html:

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("");
}

вы можете просто создать метод с несколькими replaceAll (), например

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

Используйте эту ссылку для наиболее часто используемых замен: http://tunes.org/wiki/html_20special_20characters_20and_20symbols.html

Это просто, но эффективно. Я использую этот метод сначала для удаления мусора, но не самой первой строки, т.е. replaceAll ("\ <. *?>", ""), А затем я использую определенные ключевые слова для поиска индексов, а затем использую .substring (start, end ), чтобы убрать ненужные вещи. Поскольку это более надежно, и вы можете точно указать, что вам нужно, на всей странице html.

Две заметки. Во-первых, это неоптимально - для каждого вызова replaceAll Java будет пытаться скомпилировать первый аргумент как регулярное выражение и пройти через всю строку, чтобы применить это регулярное выражение к строке, каждый раз обрабатывая несколько десятков КБ для обычной HTML-страницы. Во-вторых, рекомендуется не использовать replaceAll для замены простых (не регулярных) строк, а вместо этого использовать replace () (который также заменяет все, в отличие от названия).

cthulhu 23.12.2010 16:09

Я знаю, что это устарело, но я просто работал над проектом, который требовал от меня фильтрации HTML, и это сработало нормально:

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

вместо этого:

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

Если вы пишете для Android, вы можете сделать это ...

android.text.HtmlCompat.fromHtml(instruction, HtmlCompat.FROM_HTML_MODE_LEGACY).toString()

Отличный совет. :) Если вы показываете текст в TextView, вы также можете опустить .toString (), чтобы сохранить некоторое форматирование.

Lorne Laliberte 16.03.2012 07:40

@Branky Я не пробовал ... принятый ответ работает как шарм

Maverick 07.08.2014 17:11

Прекрасно работает. Все теги html были удалены из строки.

user3144836 03.08.2015 04:23

Это хорошо, но теги <img> заменены какими-то странными вещами. Получились квадратики, на которых было изображение

Bibaswann Bandyopadhyay 14.10.2015 18:59

@BibaswannBandyopadhyay другой ответ помогает избавляется от этих персонажей

Vince 26.03.2016 19:30

Также очень просто использовать Иерихон, и вы можете сохранить часть форматирования (например, разрывы строк и ссылки).

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

Джерико смог разобрать <br> до разрыва строки. Jsoup и HTMLEditorKit не могли этого сделать.

homaxto 24.08.2011 18:49

Jericho отлично справляется с этой задачей, много использовал в своих проектах.

Jerry Tian 24.05.2012 05:40

Иерихон работал как заклинание. Спасибо за предложение. Одно замечание: вам не нужно создавать сегмент всей строки. Source расширяет сегмент, поэтому любой из них работает в конструкторе Renderer.

MrPlow 02.09.2015 23:35

Джерико сейчас кажется немного устаревшим (последний выпуск был 3.4 в конце 2015 года). Однако, если он по-прежнему работает хорошо, значит, он по-прежнему работает хорошо!

Jonathan Hult 12.10.2017 23:22

Мои 5 центов:

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);
}

Вот еще один способ сделать это:

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;
}

Или вы можете просто сказать if (input.indexOf ("<")> 0 || input.indexOf (">")> 0) return ""; иначе вернуть ввод;

Hossein Shahdoost 21.04.2013 15:49

Для этой цели можно также использовать Апач Тика. По умолчанию он сохраняет пробелы из разделенного HTML, что может быть желательно в определенных ситуациях:

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

Обратите внимание, что метод синтаксического анализа не рекомендуется в пользу Parse.parse(InputStream, ContentHandler, Metadata, ParseContext).

Jacob van Lingen 01.07.2015 12:05

Чтобы получить форматированный простой HTML-текст, вы можете сделать это:

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/>");

Чтобы получить форматированный простой текст, измените <br/> на \ n и измените последнюю строку:

nodeValue=nodeValue.replaceAll("(\\s*\n){3,}", "<br/><br/>");

В качестве альтернативы можно использовать HtmlCleaner:

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

HtmlCleaner работает хорошо, сохраняет разрывы строк и имеет недавний выпуск (2.21 в мае 2017 года).

Jonathan Hult 12.10.2017 23:22

У принятого ответа просто Jsoup.parse(html).text() есть 2 потенциальных проблемы (с JSoup 1.7.3):

  • Удаляет разрывы строк в тексте
  • Преобразует текст &lt;script&gt; в <script>

Если вы используете это для защиты от XSS, это немного раздражает. Вот мой лучший шанс улучшить решение с использованием как JSoup, так и 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);

Обратите внимание, что последний шаг связан с тем, что мне нужно использовать вывод как простой текст. Если вам нужен только вывод HTML, вы сможете его удалить.

И вот несколько тестовых примеров (от ввода к выводу):

{"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"}

Если вы найдете способ сделать это лучше, дайте мне знать.

Это не сработает против чего-то вроде &#38;lt;script&#38;gt;alert('Evil script executed');&#38;lt;/script&#38;gt;. То же самое и с &#x26;. JSoup не конвертирует &lt;script&gt; into <script>, он это делает, потому что вы вызываете StringEscapeUtils.unescapeHtml после того, как JSoup очистил ввод.

Guillaume Polet 26.02.2015 12:59

Удалите HTML-теги из строки. Где-то нам нужно проанализировать некоторую строку, полученную некоторыми ответами, такими как Httpresponse, от сервера.

Итак, нам нужно его разобрать.

Здесь я покажу, как удалить теги HTML из строки.

    // 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

Где взять new System.Text.RegularExpressions.Regex();?

beresfordt 16.06.2015 17:41

@beresfordt этот ответ относится к .NET, а не к Java, как было запрошено в вопросе

Erin Drummond 06.08.2015 23:25

На Android попробуйте следующее:

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

Это сработало! он удалил весь встроенный html из текста :)

DritanX 15.05.2015 23:33

Вы всегда используете фрагменты кода для обычного кода. Фрагменты кода должны использоваться только для HTML, javascript или другого кода, который можно запускать в браузере. Вы не можете запустить Java в браузере. В будущем используйте обычные блоки кода ... На этот раз я отредактирую ваш ответ, исправлю форматирование и т. д., Но, пожалуйста, не делайте этого больше в будущем. Я не в первый раз говорю тебе об этом ...

Xaver Kapeller 21.05.2015 17:09

Из какой это библиотеки?

Paul Croarkin 16.06.2015 21:39

@PaulCroarkin это библиотека внутри android sdk. android.text.Html

Ameen Maheen 17.06.2015 08:07

Но это добавление большого количества пробелов или новых строк в конец моей строки. Не круто.

Rui Santos 08.07.2015 14:42

отлично работает для меня, чувак, может быть, вам стоит проверить свой ввод, например, он идет с любым таким пробелом ..

Ameen Maheen 09.07.2015 12:24

Потрясающий. Удалены все теги html.

user3144836 03.08.2015 04:22

выглядит знакомо, как и мой ответ от 2011 года.

Ken Goodridge 15.03.2016 23:27

что убрало еще одну головную боль с моей тарелки :)

nathandrake 31.03.2016 22:23

Один из способов сохранить информацию о новой строке с помощью JSoup - это поставить перед всеми тегами новой строки некоторую фиктивную строку, выполнить JSoup и заменить фиктивную строку на «\ 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");

Используйте Html.fromHtml

HTML Теги:

<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>

В соответствии с Официальная документация Android любые теги в HTML будут отображаться как общая замена Нить, которую ваша программа может затем пройти и заменить реальным струны.

Метод Html.formHtml принимает Html.TagHandler и Html.ImageGetter в качестве аргументов, а также текст для анализа.

Пример

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

Затем

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

Выход

Это текст обо мне, который пользователь может поместить в свой профиль

Никаких дополнительных утилит и соответствие с Android Docs. +1

davidbates 30.03.2016 07:17

Это должно работать -

использовать это

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

и это

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

Как правило, ответы намного полезнее, если они включают объяснение того, для чего предназначен код.

Peter 30.06.2017 14:47
classeString.replaceAll("\\<(/?[^\\>]+)\\>", "\\ ").replaceAll("\\s+", " ").trim() 

Хотя этот фрагмент кода может решить вопрос, включая объяснение действительно помогает улучшить качество вашего сообщения. Помните, что вы отвечаете на вопрос читателей в будущем, и эти люди могут не знать причины вашего предложения кода. Также постарайтесь не загромождать свой код пояснительными комментариями, это снижает удобочитаемость как кода, так и пояснений!

Filnor 26.01.2018 15:29

Вот еще один вариант, как заменить все (HTML-теги | HTML-объекты | Пустое пространство в HTML-содержимом)

content.replaceAll("(<.*?>)|(&.*?;)|([ ]{2,})", "");, где содержимым является строка.

Я немного улучшил его: {code} .replaceAll ("(<. *?>) | (&. * ?;)", "") .replaceAll ("\\ s {2,}", "") { code} Потому что часто эти теги находятся рядом с текстом. А после удаления тегов измените все 2 и более пространства записи на 1.

Ondřej Stašek 31.07.2019 14:20

Вы можете просто использовать HTML-фильтр Android по умолчанию.

    public String htmlToStringFilter(String textToFilter){

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

    }

Вышеупомянутый метод вернет строку с фильтром HTML для вашего ввода.

Я знаю, что прошло некоторое время с тех пор, как этот вопрос был задан, но я нашел другое решение, это то, что сработало для меня:

Pattern REMOVE_TAGS = Pattern.compile("<.+?>");
    Source source= new Source(htmlAsString);
 Matcher m = REMOVE_TAGS.matcher(sourceStep.getTextExtractor().toString());
                        String clearedHtml= m.replaceAll("");

Стоит отметить, что если вы пытаетесь сделать это в проекте Сервисный стек, это уже встроенное расширение строки.

using ServiceStack.Text;
// ...
"The <b>quick</b> brown <p> fox </p> jumps over the lazy dog".StripHtml();

Я часто обнаруживаю, что мне нужно только вырезать комментарии и элементы скрипта. Это надежно работало для меня в течение 15 лет и может быть легко расширено для обработки любого имени элемента в HTML или XML:

// delete all comments
response = response.replaceAll("<!--[^>]*-->", "");
// delete all script elements
response = response.replaceAll("<(script|SCRIPT)[^+]*?>[^>]*?<(/script|SCRIPT)>", "");

Иногда строка html поступает из xml с таким &lt. При использовании Jsoup нам нужно его проанализировать, а затем очистить.

Document doc = Jsoup.parse(htmlstrl);
Whitelist wl = Whitelist.none();
String plain = Jsoup.clean(doc.text(), wl);

При использовании только Jsoup.parse(htmlstrl).text() нельзя удалить теги.

Попробуйте это для javascript:

const strippedString = htmlString.replace(/(<([^>]+)>)/gi, "");
console.info(strippedString);

Вы можете использовать этот метод для удаления тегов HTML из строки,

public static String stripHtmlTags(String html) {

    return html.replaceAll("<.*?>", "");

}

Другие вопросы по теме