2010-01-18 154 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