2012-05-29 3 views
2

Предположим, у нас есть тег под названием test, то есть [code].Разрешить X только вложенные теги

Что бы я хотел сделать, это то, что я хотел бы разрешить только 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

[joke] Использовать Regex: 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 («[код] [код] 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. Он будет работать только в IE, если вы сначала запустите 'document.createElement ('test')'. – 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-ограничение: https://github.com/jacksono/jBBCode – Josh

+0

Да, вот что я имел в виду, я посмотрел на источник и их решение в основном требует использования всего этого, поскольку для него требуются классы TokenManager, Node, TextNode, ElementNode и DocumentElement (по крайней мере), и я подумал, что лучше сначала попытаться найти более элегантное решение. – Lior

Смежные вопросы