Удаление всего из строки вне указанных тегов (PHP) - PullRequest
1 голос
/ 01 декабря 2010

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

Я пытаюсь построить функцию 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>"

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

Ответы [ 3 ]

1 голос
/ 01 декабря 2010

Хорошо, так что я думаю, что я нашел способ сделать это на основе модифицированной версии функции 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>");

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

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

0 голосов
/ 01 декабря 2010

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

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

См. Основу zend.dom.query.http://framework.zend.com/manual/en/zend.dom.query.html

По сути, запросите "div img", чтобы получить теги img непосредственно внутри тегов div.Затем ползите вверх по дереву, пока не достигнете своей целевой позиции, и извлеките и сохраните externalHTML этого узла ....

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

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

0 голосов
/ 01 декабря 2010

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

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

...