2012-05-29 59 views
2

假設我們有一個名爲test的標籤,即[code]僅允許X嵌套標籤

我想要做的是,我想只允許其他[code]標籤內的每個主[code]標籤在一個字符串中,這意味着最內層的標籤將被刪除。

因此,舉例來說,如果X = 4,下列字符串:

[code]a[code]b[code]c[code]d[code]e[code]f[code]g[/code][/code][/code][/code][/code][/code][/code] 

將成爲:

[code]a[code]b[code]c[code]d[code]e[/code][/code][/code][/code][/code] 

和下面的字符串:

[code]a[code]b[code]c[code]d[code]TEST[/code][code]e[code]f[code]g[/code][/code][/code][/code][/code][/code][/code] 

將成爲:

[code]a[code]b[code]c[code]d[code]TEST[/code][code]e[/code][/code][/code][/code][/code] 

這裏的目標是在一個代碼元素中不會有多個嵌套的[code]元素,所以它不會太雜亂。

我想知道如何實現這一點,只是想想算法,並會感激任何建議。

+1

爲什麼你需要做的是什麼? – Eric

+1

[笑話]使用正則表達式:http://stackoverflow.com/a/1732454/420001 *編輯*:我認爲你需要描述你想解決的問題,而不是你的解決方案認爲會起作用。這感覺非常混亂。你最終的目標是什麼? – Josh

+1

你怎麼輸出字符串? –

回答

1

這會是相當浪費,因爲它會如此容易地添加多個標籤支持等在這裏。 你幾乎不得不完全吹出樹解析任何一種方式。

注意,無效的輸入不以任何方式處理,標籤必須保持良好的平衡

function get_node_contents($node) { 
    $orig = $node; 
    $ret = "[code]" . $node->content; 

    if(@$node->children) { 
     foreach($node->children as $node) { 
      $ret .= get_node_contents($node); 
     } 
    } 


    if(@$orig->endContent) { 
     $ret .= $orig->endContent; 
    } 
    return $ret."[/code]"; 

} 

function reduce_depth($str, $maxDepth = 4) { 
    $index = 0; 
    $len = strlen($str); 
    $reg = '/(\[code\]|\[\/code\])/'; 

    $root = new stdClass; 
    $root->children = array(); 
    $depth = 0; 
    $ret = ""; 

    $pos = strpos($str, "[code]"); 

    if($pos) { 
     $ret .= substr($str, 0, $pos - 0); 
    } 

    while($index < $len ) { 

     if(!preg_match($reg, $str, $matches, PREG_OFFSET_CAPTURE, $index)) { 
      break; 
     } 

     $index = ($matches[1][1] + strlen($matches[1][0])); 
     $tag = $matches[1][0]; 

     $next = preg_match($reg, $str, $matches, PREG_OFFSET_CAPTURE, $index); 
     $content = ""; 

     if($next) { 
      $content = substr($str, $index, $matches[1][1] - $index); 
     } 

     if($tag === "[code]") { 
      if($depth === 0) { 
       $parent = $root->children[] = new stdClass; 
       $parent->content = $content; 
       $depth++; 
      } 
      else if ($depth++ > $maxDepth) { 

       continue; 
      } 
      else { 
       if([email protected]$parent->children) { 
        $parent->children = array(); 
       } 
       $child = $parent->children[] = new stdClass; 
       $child->content = $content; 
       $child->parent = $parent; 
       $parent = $child; 
      }   
     } 
     else {     
      $depth--; 

      if(@$parent->parent) { 
       $parent = $parent->parent; 
      } 

      if(@$content) { 
       $parent->endContent = $content; 
      }     

     } 

    } 


    foreach($root->children as $node) { 
     $ret .= get_node_contents($node); 
    } 

    $ret .= substr($str, $index, $len - $index); 


    return $ret; 

} 

echo reduce_depth("asdasdas[code]l[/code][code]a[code]lol[/code][code]b[code]c[code]d[code]e[code]f[code]g[/code][/code][/code][/code][/code][/code][/code]aasdasdsasd", 4). "\n"; 
echo reduce_depth("[code]a[code]b[code]c[code]d[code]e[code]f[code]g[/code][/code][/code][/code][/code][/code][/code]", 4) . "\n"; 
echo reduce_depth("[code]a[code]b[code]c[code]d[code]TEST[/code][code]e[code]f[code]g[/code][/code][/code][/code][/code][/code][/code]", 4) . "\n"; 
echo reduce_depth("[code][code]bugi[/code]bugi2[/code]", 1) . "\n"; 
echo reduce_depth("[code][code]bugi[/code]bugi2[code]bugi3[/code]bugi4[code]bugi5[/code]bugi6[/code]", 3) . "\n"; 


/* 
    asdasdas[code]l[/code][code]a[code]lol[/code][code]b[code]c[code]d[code]e[/code][/code][/code][/code][/code]aasdasdsasd 
    [code]a[code]b[code]c[code]d[code]e[/code][/code][/code][/code][/code] 
    [code]a[code]b[code]c[code]d[code]TEST[/code][code]e[/code][/code][/code][/code][/code] 
    [code][code]bugi[/code]bugi2[/code] 
    [code][code]bugi[/code][code]bugi3[/code][code]bugi5[/code]bugi6[/code] 

*/ 
+0

令人驚訝的是,你不應該打擾,真的,我只是試圖找出如何自己。謝謝! – Lior

+0

@Lior沒有問題,我可能會在未來使用類似的代碼....也許 – Esailija

+0

嗯,試圖找出我自己的,但我無法。請嘗試運行以下命令:reduce_depth(「[code] [code] 1 [/ code] 2 [/ code]」,1);該字符串應該保持不變,但不是。代碼總是忽略[/ code]標籤之間的文本。 – Lior

0

我不知道你要什麼在這裏,但如果你這個輸出爲HTML,你可以添加此規則,以你的樣式表:

test test test test test { display: none; } 

顯然,這將有成爲一個真正的元素,因爲<test>不是html的一部分。

+1

其實.... http://jsfiddle.net/NYECW/ – Josh

+1

@Josh:不在IE中。如果你先運行'document.createElement('test')',它只會在IE中工作。 – Eric

+0

Gotcha。雖然OP只是說它是BBCode,而不是HTML,所以CSS在這種情況下可能無法工作。 – Josh

1

看起來你可以使用JBBCode:

http://jbbcode.com/docs#definingNewCodes

addBBCode's fifth and last parameter is a nest limit. By default 
the nest limit is -1, meaning no limit. Nest limits allow you to 
define a bbcode such that if the bbcode is embedded multiple times, 
elements nested beyond the nest limit will be omitted from the output. 
+0

使用他們的解決方案(當然不是整個解析器,只是他們限制嵌套的方式)是相當矯枉過正的,但是,謝謝,如果我沒有別的選擇,我會使用它。 – Lior

+0

@Lior那麼,你總是可以看看源代碼,看看它們是如何實現N-limiting的:https://github.com/jacksono/jBBCode – Josh

+0

是的,這就是我的意思,我看着源代碼和他們的解決方案基本上需要使用整個事情,因爲它需要TokenManager,Node,TextNode,ElementNode和DocumentElement類(至少),我想我最好先嚐試找到更優雅的解決方案。 – Lior