Вопрос

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

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

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

Это было полезно?

Решение

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

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

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

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

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

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

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

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

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

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

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

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

Другой способ - использовать 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();
        }
    }
}

ref: Удалить теги HTML из файла, чтобы извлечь только текст

Я думаю, что самый простой способ отфильтровать теги 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("");
}

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

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

На Android попробуйте это:

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

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

Принятый ответ: делать просто 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"}

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

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

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

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

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

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

используйте это

  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.

Принятый ответ не сработал для указанного мной теста: результат " a < b или b > & С Quot; является & "a b или b > с Quot &;.

Итак, я использовал 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, и это работало нормально:

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

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

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

Вот немного более детальное обновление, чтобы попытаться обработать некоторое форматирование для разрывов и списков. Я использовал выход 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));
    }
}

Кроме того, можно использовать HtmlCleaner :

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

Использовать 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());

Выход

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

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

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

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

Похоже, вы хотите перейти от 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;
}

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

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

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

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

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

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

Один из способов сохранить информацию о новой строке с помощью 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-фильтр Android по умолчанию

    public String htmlToStringFilter(String textToFilter){

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

    }

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

Мои 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);
}

Чтобы получить форматированный простой 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/>");
classeString.replaceAll("\\<(/?[^\\>]+)\\>", "\\ ").replaceAll("\\s+", " ").trim() 

вы можете просто создать метод с несколькими 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 (& Quot; \ & Lt;. *? & Gt; & Quot;, & Quot; quot;), а позже я использую определенные ключевые слова для поиска индексов, а затем использую метод .substring (start, end) для удаления ненужных вещей. Поскольку это более надежно, и вы можете точно указать, что вам нужно на всей HTML-странице.

Удалить теги 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
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top