正如其名字所暗示的,BBCode 广泛用在论坛程序开发中,比如 phpbb、vbb 等。存储在数据库中的字符串往往是混杂 BBCode 的,如何从这些字符串中剔除 BBCode,以提取纯文本信息?如果使用 PHP 语言,有很多现成可用的 PHP BBCode parser。但如果使用 Java 呢?似乎很难找到现成的 Java BBCode parser。当然,可以使用正则表达式来做匹配分析,不过失之繁琐。无意中,在 JBoss Portal v2.6.7 中发现了一个组件可以分析 BBCode,位于 org.jboss.portal.format.* 包中,其 jar 文件是 portal-format-lib.jar
使用方法:
ToTextRenderer render = new ToTextRenderer(); StringWriter writer = new StringWriter(); render.setWriter(writer); render.render(bbString.toCharArray(), 0, bbString.length()); String txt = writer.toString();
就是这么简单。
不过这个 JBoss Portal format 组件只支持小写的 BBCode,比如 [b] [/b],不支持大写的,比如 [B] [/B]。
可以修改源码包 org.jboss.portal.format.parser.bbcode 中的 Analyzer.flex 来实现对大写的支持:(以下大写均为我所添加)
<YYINITIAL> { "[b]" | "[B]" { return token(OPEN_B, null); } "[/b]" | "[/B]" { return token(CLOSE_B, null); } "[i]" | "[I]" { return token(OPEN_I, null); } "[/i]" | "[/I]" { return token(CLOSE_I, null); } "[u]" | "[U]" { return token(OPEN_U, null); } "[/u]" | "[/U]" { return token(CLOSE_U, null); } "[color="(([A-Za-z]+)|("#"[0-9A-Fa-f]{6}))"]" { return token(OPEN_COLOR, yytext().substring(7, yytext().length() - 1)); } "[COLOR="(([A-Za-z]+)|("#"[0-9A-Fa-f]{6}))"]" { return token(OPEN_COLOR, yytext().substring(7, yytext().length() - 1)); } "[/color]" | "[/COLOR]" { return token(CLOSE_COLOR, null); } "[size="[0-9]{1,2}"]" { return token(OPEN_SIZE, yytext().substring(6, yytext().length() - 1)); } "[SIZE="[0-9]{1,2}"]" { return token(OPEN_SIZE, yytext().substring(6, yytext().length() - 1)); } "[/size]" | "[/SIZE]" { return token(CLOSE_SIZE, null); } "[quote]" | "[QUOTE]" | "[Quote]" { return token(OPEN_QUOTE_ANONYMOUS, null); } "[quote="~["]"] { return token(OPEN_QUOTE, yytext().substring(7, yytext().length() - 1)); } "[QUOTE="~["]"] { return token(OPEN_QUOTE, yytext().substring(7, yytext().length() - 1)); } "[Quote="~["]"] { return token(OPEN_QUOTE, yytext().substring(7, yytext().length() - 1)); } "[/quote]" | "[/QUOTE]" | "[/Quote]" { return token(CLOSE_QUOTE, null); } "[code]" | "[CODE]" | "[Code]" { return token(OPEN_CODE, null); } "[/code]" | "[/CODE]" | "[/Code]" { return token(CLOSE_CODE, null); } "[list]" | "[LIST]" | "[List]" { return token(OPEN_LIST_UNORDERED, null); } "[list=1]" | "[LIST=1]" | "[List=1]" { return token(OPEN_LIST_ORDERED_NUMERICAL, null); } "[list=a]" | "[LIST=a]" | "[List=a]" { return token(OPEN_LIST_ORDERED_ALPHABETICAL, null); } "[/list]" | "[/LIST]" | "[/List]" { return token(CLOSE_LIST, null); } "[*]" { return token(LIST_ITEM, null); } "[url"~["]"]~["["]"/url]" { return token(LINK, yytext().substring(4, yytext().length() - 6)); } "[URL"~["]"]~["["]"/URL]" { return token(LINK, yytext().substring(4, yytext().length() - 6)); } .|\n { return token(TEXT, yytext()); } }
使用 JFlex 来生成对应的 Analyzer.java 文件,然后将编译好的 Analyzer.class 放到 portal-format-lib.jar 中替换原先的 class。
另外一个问题是,不支持用户自定义的 BBCode。我还没有找到简单易行的解决方案,以后再想吧。
[UPDATE] 3 Mar 2010
这篇文章已过时,有更好的方法。
Pingback: Use KefirBB to Extract Text from BBCode String | 细柳营