Parsing 解析任意用户输入
我有一个数据库,里面有来自公告栏的信息。电路板使用BB代码作为格式样式。即:Parsing 解析任意用户输入,parsing,user-input,Parsing,User Input,我有一个数据库,里面有来自公告栏的信息。电路板使用BB代码作为格式样式。即: 我没有格式化 这是[b]粗体[/b]文本 标记也可以[i][b]嵌套[/b] 而且筑巢可能相当丑陋 我的最终目标是将这些消息转换为一些格式良好的XML(这里没有讨论;)。我不想使用正则表达式,因为正则表达式在某一点上会失败(事实上,它确实会失败) 第一步:将消息解析为某种内部表示(图形、树等)。我被困在这一点上。实际提取并没有那么大的问题,但存储是 如何将这种标记表示为某种有意义的结构。我的问题似乎与浏览器从HTM
- 我没有格式化
- 这是[b]粗体[/b]文本
- 标记也可以[i][b]嵌套[/b]
- 而且筑巢可能相当丑陋
“而[b]嵌套[i]可能相当丑陋”
。(如果您以后不需要将其转换为XML,我认为这是不必要的。如果不需要转换为XML,您可以保留一个文本节的链接列表,其中每个节都标记有其格式组合)
我想到了解决这个问题的两种可能的方法(当然可能有更好的方法)。1) 预处理并在必要时插入缺少的结束和开始标记。2) 构建解析树,如果存在重叠的标记,则根据当前上下文暗示缺少的标记。我认为方法(2)会更简单、更干净
您可以基于复合模式对树进行建模,其中有一个AbstractElement类、一个扩展AbstractElement的TextElement类和一个扩展AbstractElement并包含AbstractElement类型子元素列表的标记类
首先创建一个根标记实例。然后调用rootTag.parse(text)。您需要一个扫描仪,它可以返回3种类型的标记:文本、开始标记和结束标记。扫描仪将允许您将令牌推送到它上面,它将在任何正常扫描令牌之前返回。这将允许您在遇到并处理意外的结束标记后推送新的开始标记标记。您还必须知道何时完成输入。我将使用第四种令牌类型
/* methods within class Tag */
public void parse(String text) {
MyScanner scanner = new MyScanner(text);
parse(scanner);
}
/* returns next token */
private Token parse(MyScanner scanner) {
Token firstToken = scanner.getNextToken();
return parse(scanner,firstToken);
}
private Token parse(MyScanner scanner) {
Token firstToken = scanner.getNextToken();
return parse(scanner,firstToken);
}
private Token parse(MyScanner scanner, Token token) {
while (!token.isDone() && !token.isEndTag()) {
if (token.isStartTag()) {
Tag subTag = new Tag(token.getValue());
token = scanner.getNextToken();
token = subTag.parse(scanner,token);
addElement(subTag);
}
else {
TextElement text = new TextElement(token.getValue());
addElement(text);
token = scanner.getNextToken();
}
}
if (token.isEndTag()) {
if (!token.getValue().equals(getName()) {
scanner.push(new Token(Token.START_TAG,token.getValue()));
}
else {
token = scanner.getNextToken();
}
}
return token;
}
/*类标记中的方法*/
公共void解析(字符串文本){
MyScanner scanner=新的MyScanner(文本);
解析(扫描器);
}
/*返回下一个令牌*/
专用令牌解析(MyScanner扫描程序){
Token firstToken=scanner.getNextToken();
返回解析(scanner,firstToken);
}
专用令牌解析(MyScanner扫描程序){
Token firstToken=scanner.getNextToken();
返回解析(scanner,firstToken);
}
专用令牌解析(MyScanner扫描程序、令牌){
而(!token.isDone()&&!token.isEndTag()){
if(token.isStartTag()){
Tag subTag=新标记(token.getValue());
令牌=scanner.getNextToken();
token=subTag.parse(扫描器,token);
附加元素(子标记);
}
否则{
TextElement text=新的TextElement(token.getValue());
增编(文本);
令牌=scanner.getNextToken();
}
}
如果(token.isEndTag()){
如果(!token.getValue().equals(getName()){
push(新令牌(Token.START_标记,Token.getValue());
}
否则{
令牌=scanner.getNextToken();
}
}
返回令牌;
}
因此,如果要解析“并且[b]嵌套[i]可能相当丑陋”,那么应该创建以下内容
rootTag.parse should be adding:
TextElement: "And the "
Tag: "b"
TextElement: "nesting "
Tag: "i"
TextElement: "can be"
(... at this point the odd [/b] is encountered ...)
(... push "i" start tag on the scanner ...)
(... here the [/b] is encountered (again) ...)
Tag: "i" (this was scanned because it had been pushed to the scanner)
TextElement: " rather"
TextElement: " ugly"
rootTag.parse应添加:
TextElement:“和”
标签:“b”
TextElement:“嵌套”
标签:“我”
TextElement:“可以”
(…此时遇到了奇怪的[/b]。)
(…按下扫描仪上的“i”开始标签…)
(…这里遇到了[/b]。)
标签:“i”(这是扫描的,因为它被推到了扫描仪上)
TextElement:“相当”
TextElement:“丑陋”
注意:在文本区域中进行编码不利于测试和调试。请接受此答案作为提示或可能性,而不是您定义的答案。Wow。非常感谢。您的示例代码几乎解决了我的所有问题:)谢谢您,祝您好运。我刚刚修正了一个输入错误,我在push调用中传递了错误的参数,现在也修正了。