Removing everything from string outside specified tags (PHP)
Question has been updated to exclude regex as a possible solution.
I'm trying to build a php function which will allow me strip everything outside of specified tags while preserving the specified tags and their content and am not sure how to do this...
For example:
$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>"
Thanks for any help!
Ok, so I think I figured out a way to do this based on a modified version of the explode_tags function I posted a link to above:
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>");
This seems to work perfectly so far, although I have only tried it on a few different pieces of content. I'm not great at this, so if anybody has suggestions please share freely...
Thanks for all of your answers!
Jeff Atwood has a really great blog post arguing against using regex for parsing HTML. http://www.codinghorror.com/blog/2008/06/regular-expressions-now-you-have-two-problems.html
However, in this situation, it might not be a bad idea to use regex to first remove the extranious ends and then use a DOM parser to pick out the structures you want from the inside.
update based on the comment
You could use css selectors to grab the divs you are looking for, then crawl up the tree to get the outermost element of your selection.
See the zend.dom.query framework. http://framework.zend.com/manual/en/zend.dom.query.html
Basically query for "div img" to get the img tags immediately inside div tags. Then crawl up the tree until you reach your target position, and extract and save that node's outerHTML....
This would work in Javascript, but I don't know about php.
The caveats here are that you lose the specificity of your example above. ie: a div containing four images would have matches for all child images... You'd have to do some extra processing to ensure you're really doing what you think you are doing. However, it's a bit safer than blind string replacement.
精彩评论