2010-01-18 153 views
1

我有一个完整的从公告板的消息的数据库。该板使用BB代码作为格式化样式。即:解析arbitary用户输入

  • 我没有格式化
  • 这是[B]大胆[/ B]文本
  • 标签也[I] [B]是[/ B]嵌套[/ i]于
  • 而[b]嵌套[I]可以[/ b],而[/ i]于丑

我的最终目标是将这些信息转换为某种格式良好的XML(这里不讨论;))。我不想使用正则表达式,这在某些时候会失败(事实上:它的确如此)。

第一步:解析的消息变成某种内部表示(图表,树等)的。而且我被困在这一点上。实际的提取不是那么大的问题,但存储是。

如何表示这种标记到一些有意义的结构。我的问题似乎与从HTML文件构建DOM的浏览器类似(或几乎相同)。所以我认为有一些策略可以解决它。我知道这个解决方案并不完美,但我愿意投入大量的时间来建立最好的可能。

问题:你有任何提示/提示/评论?您可以推荐的任何文章或论文?或者讨论这些话题的书?我很感激任何意见。

回答

2
而[B]嵌套[I]可以[/ B],而[/ i]于丑

我已经写了非常相似,你正在寻找不同的是它做什么解析器会在你的第四个例子上抛出一个错误。 “[i]中的”意外结束标记[/ b]“)。

我认为你需要做的是非常可行的,但在内部,你会想创建一个树,如果你的原文是:

"And the [b]nesting [i]can be[/i][/b][i] rather[/i] ugly"。 (如果以后不需要将其转换为XML,我认为这不是必需的,如果不需要转换为XML,则可以保留一个链接的文本部分列表,其中每个部分都标有其格式组合)

两种可能的方法对这一问题浮现在脑海中(当然可能有更大的可能性)。 1)预处理并插入缺失的末端,并在必要时开始标记。 2)构建你的分析树,并在有重叠标记的地方暗示基于当前上下文的缺失树。我认为方法编号(2)会更简单和更清晰。

你可以根据你在哪里有一个AbstractElement类,扩展AbstractElement对于TextElement类,以及延伸AbstractElement,并包含类型AbstractElement的子元素列表的标签类的复合模式,将树模型。

您将通过创建一个根标签的实例启动。然后你会调用rootTag.parse(文本)。您需要一个可以返回3种令牌的扫描器:文本,开始标签和结束标签。扫描仪将允许您将令牌推送到它上面,它会在任何正常扫描的令牌之前返回。这将允许您在遇到并处理意外的结束标记后推送新的开始标记标记。您还需要知道何时完成输入。我将为此使用第4种标记类型。

 
    /* 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; 
    } 

所以,如果你是解析 “和[b]嵌套[I]可以[/ 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" 

注意:文本区域内的编码不适合测试和调试。接受这个答案作为提示或可能性,而不是你的确定答案。

+0

哇。非常感谢你。你的示例代码几乎解决了我所有的问题:) – 2010-01-20 11:20:44

+0

谢谢,祝你好运。我只是修正了一个错字,并且在推送调用中传递了错误的参数,现在也修复了这个错误。 – rayd09 2010-01-20 17:06:44