我的Web应用程序托管用户编写的一系列文档,并通过PrimeFaces使用CLEditor编辑器进行编辑。文档可以是任何大小,并且具有用户选择的任何格式。
我想要做的是将文档的第一行视为标题,这样当我创建这些文档的列表时我只显示标题,然后用户可以单击该表行来查看整个文档。我用
显示标题<h:outputText value="#{backBean.doc}" escape="false" />
我所做的是将文档的子字符串拉出,直到但不包括 br 标记的第一个模式。除非用户应用跨越该格式的格式,否则这种方法有效。生成的字符串包含未公开的HTML标记,通常为 div 或 span ),当输出它们而不转义时,它们会干扰甚至消隐页面的其余部分。
所以我正在寻找一个简单的解决方案来修复HTML片段。我宁愿不导入一个巨大的库,比如JTidy,因为它会引入我现在没有的各种依赖,就像DOM解析器一样,等等。任何人都可以提出更便宜但更强大的解决方案吗?有没有办法在客户端清理它?
答案 0 :(得分:2)
我建议Jsoup。
要解析HTML并获取其<body>
内容,这就是这个oneliner的问题:
String htmlBody = Jsoup.parse(userInput).body().html();
顺便说一下,由于您似乎打算重新显示未转义的用户控制HTML,因此我强烈建议您whitelist阻止XSS。 E.g。
String safeHtmlBody = Jsoup.clean(htmlBody, Whitelist.basic());
这样你可以安全地重新显示它而不用担心XSS攻击漏洞:
<h:outputText value="#{bean.safeHtmlBody}" escape="false" />
答案 1 :(得分:1)
您应该以某种方式转义文档的部分内容,否则用户可以上传包含会损害您网站的HTML / JavaScript代码的文档。如您所见,即使是简单的格式也可以打破它。一种解决方案可能是删除所有标签(通过正则表达式,字符串替换等),然后转义标题。
答案 2 :(得分:0)
我找出了JTidy的做法。这对我来说似乎非常苛刻,但我会继续使用它,直到建议更好的东西。此外,如果其他人处于这种情况,它可能会有用:
public class TitleRTF {
private static final Pattern pTidy = Pattern.compile("<body>(.*)</body>");
public TitleRTF() {}
public static String getTitle(String rtfSource) {
org.w3c.tidy.Tidy tidy = new org.w3c.tidy.Tidy();
tidy.setQuiet(true);
ByteArrayInputStream bais = new ByteArrayInputStream(rtfSource.getBytes());
org.w3c.dom.Document doc = tidy.parseDOM(new BufferedInputStream(bais), null);
try {
Transformer tr = TransformerFactory.newInstance().newTransformer();
StreamResult result = new StreamResult(new StringWriter());
NodeList list = doc.getElementsByTagName("body");
if (list.getLength() > 0) {
DOMSource source = new DOMSource(list.item(0));
tr.transform(source, result);
String text = result.getWriter().toString();
Matcher m = pTidy.matcher(text);
if (m.find()) return m.group(1);
}
} catch (TransformerException ex) { }
return "(not parsable)";
}
}
需要添加一件事是让JTidy不要记录它看作HTML错误的内容。 setQuiet(true)似乎没有这样做。