使用Jsoup.clean清除HTML内容时不添加HTML实体。

29

我正在使用某些方法清除一些不需要的HTML标签(例如<script>

String clean = Jsoup.clean(someInput, Whitelist.basicWithImages());

问题在于它将例如å替换为&aring;(这对我造成麻烦,因为它不是“纯 XML”)。

例如:

Jsoup.clean("hello å <script></script> world", Whitelist.basicWithImages())
产生的结果。
"hello &aring;  world"

但是我想要

"hello å  world"

有没有一种简单的方法来实现这个?(即比在结果中将&aring;转换回å更简单的方法。)

7个回答

37
你可以配置Jsoup的转义模式:使用 EscapeMode.xhtml 将会使输出不带实体字符。
以下是一个完整的代码片段,它接受输入的 str,并使用 Whitelist.simpleText() 进行清理:
// Parse str into a Document
Document doc = Jsoup.parse(str);

// Clean the document.
doc = new Cleaner(Whitelist.simpleText()).clean(doc);

// Adjust escape mode
doc.outputSettings().escapeMode(EscapeMode.xhtml);

// Get back the string of the body.
str = doc.body().html();

注意:与 Cleaner 对象 直接交互,建议使用 Jsoup 中的 clean 方法 - Dave Jarvis

11

Jsoup的网站上已经有一些功能请求。你可以通过添加新的空映射和新的转义类型来扩展源代码。如果你不想这样做,你可以使用apache commons中的StringEscapeUtils。

public static String getTextOnlyFromHtmlText(String htmlText){
    Document doc = Jsoup.parse( htmlText );
    doc.outputSettings().charset("UTF-8");
    htmlText = Jsoup.clean( doc.body().html(), Whitelist.simpleText() );
    htmlText = StringEscapeUtils.unescapeHtml(htmlText);
    return htmlText;
}

1
Frank,使用StringEscapeUtils方法是个好主意。非常有用,不仅在这种情况下。 - frandevel
3
这是一个非常糟糕的想法。如果输入是“<script>alert('Hello');</script>”,你实际上将注入不安全的HTML并允许XSS攻击。 - Guillaume Polet
这个功能现在已经在Jsoup中实现了。请参见Parser.unescapeEntities,https://jsoup.org/apidocs/org/jsoup/parser/Parser.html - Andreas Lundgren
@GuillaumePolet 有趣的观点,那么你如何清理这样的输入 &lt;script&gt;alert('Hello');&lt;/script&gt; - bsingh

5

来自 &bmoc 的答案是可行的,但您也可以使用更简洁的解决方案:

// Clean html
Jsoup.clean(someInput, "yourBaseUriOrEmpty", Whitelist.simpleText(), new OutputSettings().escapeMode(EscapeMode.xhtml))

2
一种更简单的方法是:
// clean the html
String output = Jsoup.clean(html, Whitelist.basicWithImages());

// Parse string into a document
Document doc = Jsoup.parse(output);

// Adjust escape mode
doc.outputSettings().escapeMode(EscapeMode.xhtml);

// Get back the string
System.out.println(doc.body().html());

我已经测试过了,它可以工作。

2

被接受的答案使用了 Jsoup.parse,看起来比在源代码中快速浏览后发现的 Jsoup.clean 更加重量级。

我复制了 Jsoup.clean(...) 的源代码,并添加了一行设置转义模式的代码。这应该避免了解析整个html文档所做的一些不必要的步骤,而只需处理一个片段。

private String clean(String html, Whitelist whitelist) {
    Document dirty = Jsoup.parseBodyFragment(html, "");
    Cleaner cleaner = new Cleaner(whitelist);
    Document clean = cleaner.clean(dirty);
    clean.outputSettings().escapeMode(EscapeMode.xhtml);
    return clean.body().html();
}

1
简单的方法:
EscapeMode em = EscapeMode.xhtml;
em.getMap().clear();

doc.outputSettings().escapeMode(em);

这将删除所有HTML实体,包括这些:', ", & ,< and >EscapeMode.xhtml 允许这些实体。

0
将HTML解析为文档,然后使用清理器清理文档并生成另一个文档,获取文档的outputSettings并设置适当的字符集和转义模式为xhtml,然后将文档转换为字符串。未经测试,但应该可以工作。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接