从某些RTF / HTML文本中提取第一个格式化的行

时间:2012-04-01 15:12:09

标签: html jsf-2

好吧,我把自己画在了这个角落的一个角落里,还没有决定出路。

我的Web应用程序托管用户编写的一系列文档,并通过PrimeFaces使用CLEditor编辑器进行编辑。文档可以是任何大小,并且具有用户选择的任何格式。

我想要做的是将文档的第一行视为标题,这样当我创建这些文档的列表时我只显示标题,然后用户可以单击该表行来查看整个文档。我用

显示标题
<h:outputText value="#{backBean.doc}" escape="false" />

我所做的是将文档的子字符串拉出,直到但不包括 br 标记的第一个模式。除非用户应用跨越该格式的格式,否则这种方法有效。生成的字符串包含未公开的HTML标记,通常为 div span ),当输出它们而不转义时,它们会干扰甚至消隐页面的其余部分。

所以我正在寻找一个简单的解决方案来修复HTML片段。我宁愿不导入一个巨大的库,比如JTidy,因为它会引入我现在没有的各种依赖,就像DOM解析器一样,等等。任何人都可以提出更便宜但更强大的解决方案吗?有没有办法在客户端清理它?

3 个答案:

答案 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)似乎没有这样做。