有没有一种好的方法从Java字符串中删除HTML?像简单的正则表达式
replaceAll("\\<.*?>", "")
会起作用,但是像&
这样的东西不会正确地转换,两个尖括号之间的非HTML内容将被删除(即正则表达式中的.*?
将消失)。
有没有一种好的方法从Java字符串中删除HTML?像简单的正则表达式
replaceAll("\\<.*?>", "")
会起作用,但是像&
这样的东西不会正确地转换,两个尖括号之间的非HTML内容将被删除(即正则表达式中的.*?
将消失)。
使用HTML解析器而不是正则表达式。这在Jsoup中非常简单。
public static String html2text(String html) {
return Jsoup.parse(html).text();
}
Jsoup还支持根据可定制的白名单删除HTML标签,如果你只想允许例如<b>
,<i>
和<u>
之类的标签,这非常有用。
Jsoup#clean()
来实现这一点。它是一个白名单过滤器,可以让您从HTML中删除所有不被允许的标记和属性,而不会更改原始内容。有关详细信息,请参见http://jsoup.org/cookbook/cleaning-html/whitelist-sanitizer。 - BalusC<p>Lorem ipsum 1 < 3 dolor sit amet</p>
上这种方法彻底失败了。再次强调,HTML不是正则语言。我完全不明白为什么每个人都试图在它上面使用正则表达式来解析感兴趣的内容,而不是使用真正的解析器。” - BalusCJsoup.clean(unsafeString, "", Whitelist.none(), new OutputSettings().prettyPrint(false));
保留换行符。 - Marc Johnen如果你正在为Android编写代码,可以这样做...
androidx.core.text.HtmlCompat.fromHtml(instruction, HtmlCompat.FROM_HTML_MODE_LEGACY).toString()
注:此处为代码示例,不提供解释。androidx.core.text
包代替旧版的android.text
。 - Ricard如果用户输入 <b>hey!</b>
,你想要显示 <b>hey!</b>
还是 hey!
? 如果是前者,只需要将小于号(<)进行转义并对安帕赛德符号进行 HTML 编码(可选引号),即可。如果是后者,则需要对代码进行修改:
replaceAll("\\<[^>]*>","")
如果用户输入了类似于<bhey!</b>
这样格式不正确的内容,你将会遇到问题。
你还可以查看JTidy,它将解析“脏”的HTML输入,并应该为您提供一种删除标记、保留文本的方法。
试图剥离HTML的问题在于浏览器有着非常宽松的解析器,比你能找到的任何库都要宽松,因此即使你尽你最大努力剥离所有标记(使用上面的替换方法、DOM库或JTidy),你仍然需要确保编码任何剩余的HTML特殊字符以保持输出安全。
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标签最简单的方法是:
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("");
}
在 Android 上,尝试这样做:
String result = Html.fromHtml(html).toString();
使用Jericho非常简单,您可以保留某些格式(例如换行和链接)。
Source htmlSource = new Source(htmlText);
Segment htmlSeg = new Segment(htmlSource, 0, htmlSource.length());
Renderer htmlRend = new Renderer(htmlSeg);
System.out.println(htmlRend.toString());
使用简单的Jsoup.parse(html).text()
作为答案有两个潜在问题(JSoup 1.7.3):
<script>
转换为<script>
如果你使用它来防止XSS攻击,这有点麻烦。以下是我最好的改进方案,同时使用JSoup和Apache StringEscapeUtils:
// breaks multi-level of escaping, preventing &lt;script&gt; to be rendered as <script>
String replace = input.replace("&", "");
// decode any encoded html, preventing <script> 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\"/>", ""},
{"<script>", ""},
{"&lt;script&gt;", "lt;scriptgt;"}, // best effort
{"\" ' > < \n \\ é å à ü and & preserved", "\" ' > < \n \\ é å à ü and & preserved"}
如果你找到了使它变得更好的方法,请告诉我。
&lt;script&gt;alert('Evil script executed');&lt;/script&gt;
这样的内容。同样适用于&
。JSoup不会将<script>
转换为<script>
,它之所以这样做是因为在JSoup清理输入后调用了StringEscapeUtils.unescapeHtml
。 - Guillaume Polet这应该有效 -
使用这个
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 , &, > etc.
HTML转义真的很难做到正确-我强烈建议使用库代码来处理,因为这比你想象的要微妙得多。查看Apache的StringEscapeUtils,这是一个相当不错的Java库。