首页 文章

从String中删除HTML标记

提问于
浏览 1456
376

有没有一种从Java字符串中删除HTML的好方法?一个简单的正则表达式

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

会工作,但像 &amp; 这样的东西不会被正确转换,并且两个尖括号之间的非HTML将被删除(即正则表达式中的 .*? 将消失) .

27 回答

  • 505

    要获得 formateed plain html text ,您可以这样做:

    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, "
    "); nodeValue=nodeValue.replaceAll("(\\s*<br[^>]*>){3,}", "

    ");

    要通过\ n获得 formateed plain text 更改
    并更改最后一行:

    nodeValue=nodeValue.replaceAll("(\\s*\n){3,}", "

    ");
  • 259

    使用Jericho也很简单,你可以保留一些格式(例如换行符和链接) .

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

    从字符串中删除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
    
  • 27

    这应该工作 -

    用这个

    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.
    
  • 20

    这是另一种方法:

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

    为此还可以使用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())
    
  • 15

    使用JSoup保留换行信息的一种方法是在所有新行标签之前加上一些虚拟字符串,执行JSoup并用“\ n”替换虚拟字符串 .

    String html = "<p>Line one</p><p>Line two</p>Line three
    etc."; String NEW_LINE_MARK = "NEWLINESTART1234567890NEWLINEEND"; for (String tag: new String[]{"</p>","
    ","</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");
  • 12

    如果你正在为 Android 写作,你可以这样做......

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

    在剥离HTML之前,你可能想要用换行符替换
    </p> 标签,以防止它成为一个难以辨认的混乱,正如蒂姆建议的那样 .

    我可以考虑删除HTML标记但将非HTML放在尖括号之间的唯一方法是检查list of HTML tags . 沿着这些方向......

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

    然后HTML解码特殊字符,如 &amp; . 结果不应被视为消毒 .

  • 6

    简单地做 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"}
    

    如果您找到了改善它的方法,请告诉我 .

  • 4

    使用HTML解析器而不是正则表达式 . 使用Jsoup这很简单 .

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

    Jsoup还针对可自定义的白名单删除了HTML标记,如果您只想允许白名单,则非常有用 . <b><i><u> .

    另见:

  • 4

    对于我指出的测试案例,接受的答案对我不起作用:“a <b或b> c”的结果是“a b或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 {
    }
    }
    
  • 4

    这是一个更轻松的更新,试图处理中断和列表的一些格式 . 我用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
    What is happening?<p>this is a
    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)); } }
  • 4

    你可以简单地用多个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页面中您需要的内容 .

  • 3

    在Android上,试试这个:

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

    使用 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’s official DocumentationsHTML 中的任何标签都将显示为通用替换 String ,您的程序可以通过该替换 strings 替换为真实 strings .

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

    产量

    This is about me text that the user can put into their profile

  • 3

    还有一种方法可以使用com.google.gdata.util.common.html.HtmlToText类

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

    这不是防弹代码,当我在维基百科条目上运行时,我也得到了样式信息 . 但是,我相信对于小型/简单的工作,这将是有效的 .

  • 3

    我知道这是旧的,但我只是在研究一个需要我过滤HTML的项目,这很好用:

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

    而不是这个:

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

    我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);
    }
    
  • 2

    另一种方法是使用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:Remove HTML tags from a file to extract only the TEXT

  • 2

    或者,可以使用HtmlCleaner

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

    以下是如何替换所有内容的另一种变体(HTML标签| HTML实体| HTML内容中的空白空间)

    content.replaceAll("(<.*?>)|(&.*?;)|([ ]{2,})", ""); 其中content是String .

  • 0

    我认为过滤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("");
    }
    
  • 0

    听起来你想要从HTML转到纯文本 .
    如果是这种情况,请访问www.htmlparser.org . 这是一个从URL中找到的html文件中删除所有标记的示例 .
    它使用org.htmlparser.beans.StringBean .

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

    例如:classeString.replaceAll(“\ <(/?[^>])>”,“\”).replaceAll(“\ s”,“”) . trim()

  • -1

    如果用户输入 <b>hey!</b> ,是否要显示 <b>hey!</b>hey! ?如果第一个,逃避少数,和html编码&符号(和可选的引号),你没事 . 对代码实施第二个选项的修改是:

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

    但如果用户输入格式错误的内容(例如 <bhey!</b> ),您将遇到问题 .

    您还可以查看JTidy,它将解析"dirty" html输入,并应该为您提供一种方法来删除标记,保留文本 .

    尝试剥离html的问题是浏览器具有非常宽松的解析器,比你能找到的任何库都宽松,所以即使你尽力剥离所有标签(使用上面的替换方法,DOM库或JTidy) ,您仍然需要确保编码任何剩余的HTML特殊字符,以确保您的输出安全 .

  • -1

    HTML Escaping真的很难做到 - 对于一个用Java来处理这个问题的相当不错的库,我比'd definitely suggest using library code to do this, as it'更加微妙 .

相关问题