2010-11-30 1 views
1

Вопрос обновлен, чтобы исключить регулярное выражение как возможное решение.Удаление всего из строки за пределами указанных тегов (PHP)

Я пытаюсь построить функцию PHP, которая позволит мне раздеться все за пределами указанных тегов, сохраняя при этом указанные теги и их содержание, и я не знаю, как это сделать ...

Например:

$string = "lorem ipsum <div><p>Some video content</p><object></object></div><p>dolor sit</p> amet <img>" 

some_function($string, "<div><img>"); 
returns: "<div><p>Some video content</p><object></object></div><img>" 

Спасибо за любую помощь!

+0

Это даже не действительный HTML ... – KingCrunch

+2

* «Я чувствую, что это должно быть легко, но не могу понять ...» * - Потому что это непросто. – Tomalak

+2

Возможно, наиболее связанный с вопросом вопрос о переполнении стека: http://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags –

ответ

0

У Джеффа Этвуда есть действительно замечательное сообщение в блоге, в котором аргумент против использования регулярного выражения для разбора HTML. http://www.codinghorror.com/blog/2008/06/regular-expressions-now-you-have-two-problems.html

Однако в этой ситуации может быть плохой идеей использовать регулярное выражение, чтобы сначала удалить внешние разделы, а затем использовать парсер DOM для выбора структур, которые вы хотите изнутри.

0

обновления на основе комментария

Вы можете использовать CSS селекторы, чтобы захватить дивы, которые вы ищете, а затем ползти вверх по дереву, чтобы получить самый наружный элемент вашего выбора.

См. Раздел zend.dom.query. http://framework.zend.com/manual/en/zend.dom.query.html

В основном запрос для «div img», чтобы сразу получить теги img внутри тегов div. Затем сканирование вверх по дереву, пока вы не достигнете своего целевого положения, и извлеките и сохраните внешний HHML этого узла ....

Это будет работать в Javascript, но я не знаю о php.

Опасения здесь в том, что вы теряете специфику своего примера выше. т.е.: div, содержащий четыре изображения, будет иметь совпадения для всех дочерних образов ... Вам нужно будет сделать дополнительную обработку, чтобы убедиться, что вы действительно делаете то, что, по вашему мнению, делаете. Тем не менее, это немного безопаснее замены слепой строки.

+0

Это то, что я пытался сделать до сих пор, хотя у меня возникают трудности с динамическим содержанием ... на данный момент я пытаюсь изменить explode_tags функция (размещена в нижней части страницы: http://theserverpages.com/php/manual/en/function.explode.php), чтобы включить все в тег. – Eli

+0

Вы можете попробовать что-то сумасшедшее, как селектор CSS. Обновленный код выше. – Gopherkhan

1

Хорошо, так что я думаю, что я придумал, как сделать это на основе модифицированной версии функции explode_tags я отправил ссылку выше:

function explode_tags($chr, $str) { 
    for ($i=0, $j=0; $i < strlen($str); $i++) { 
     if ($str{$i} == $chr) { 
      while ($str{$i+1} == $chr) $i++; 
      $j++; 
      continue; 
     } 
     if ($str{$i} == "<") { 
      if (strlen($res[$j]) > 0) $j++; 
      $s = strpos($str, " ", $i); 
      $b = strpos($str, ">", $i); 
      if($s<$b) $end = $s; 
      else $end = $b; 
      $t = substr($str, $i+1, $end-$i-1); 
      $tend = strpos($str, ">", $i); 
      $tclose = strpos($str, "</".$t, $tend); 
      if($tclose!==false) $pos = strpos($str, ">", $tclose); 
      else $pos = strpos($str, ">", $i); 
      $res[$j] .= substr($str, $i, $pos - $i+1); 
      $i += ($pos - $i); 
      $j++; 
      continue; 
     } 
     if ((($str{$i} == "\n") || ($str{$i} == "\r")) && (strlen($res[$j]) == 0)) continue; 
     $res[$j] .= $str{$i}; 
    } 
    return $res; 
} 
function filter_tags($content, $tags) { 
    $content = strip_tags($content, $tags); 
    $tags = substr($tags, 1, -1); 
    $d = strpos($tags, "><"); 
    if($d===false) $tags = array($tags); 
    else $tags = explode("><", $tags); 
    $content = explode_tags("", $content); 
    $result=""; 
    foreach($content as $c) { 
     $s = strpos($c, " "); 
     $b = strpos($c, ">"); 
     if($s<$b) $end = $s; 
     else $end = $b; 
     $tag = substr($c, 1, $end-1); 
     if(in_array($tag, $tags)) $result.=$c; 
    } 
    return $result; 
} 

filter_tags($content, "<img><div><object><embed><iframe><param><script>"); 

Это, кажется, работает прекрасно до сих пор, хотя я только попробовали это на нескольких разных частях контента. Я не очень хорош в этом, поэтому, если у кого есть предложения, пожалуйста, поделитесь свободно ...

Спасибо за все ваши ответы!