note 88908 added to function.substr
| From: | alex at sirensclef dot com | Date: | Thu, 12 Feb 2009 21:03:46 +0000 |
| Subject: | note 88908 added to function.substr | ||
| Groups: | php.notes | ||
| Request: | Send a blank email to php-notes+get-150590@lists.php.net to get a copy of this message | ||
Here's a quick and dirty function to cut text after the specified number of words, but accounts
for XHTML strings. For example:
echo summarize('<div><p>This is a test of the summarize
function.</p></div><div>This is something else.</div>',7);
gives: <div><p>This is a test of the summarize...</p></div>
Obviously not something you want to overuse for performance reasons, but there's a fast path
for strings that don't contain tags and therefore don't need the extra work.
function summarize($str,$limit) { // summarize text up to $limit words, compatible with XHTML
strings
static $dom;
static $limit_reached;
static $word_count;
if (is_scalar($str) && strpos($str,'<')===false) return sizeof(explode('
',$str)>$limit) ? implode(' ',array_slice(explode('
',$str),0,$limit)).'...' : $str; // if string does not contain any tags, do a regular
word trim
if (is_scalar($str)) { // if this is the first call
$dom=new DOMDocument; // create a dom document
if (!@$dom->loadXML('<root>'.$str.'</root>')) return $str; //
try to load the string, returning the original string if failed
$word_count=0; // init word counter
$limit_reached=false; // init limited reached flag
};
if (is_object($str)) {$node=$str;} // if this is a recursive call, used the passed node
else $node=$dom->documentElement; // else use the root element
foreach($node->childNodes as $child) if ($child->nodeType==3) { // loop through child text
nodes
if ($limit_reached) {$node->replaceChild($dom->createTextNode('%removed_node%'),
$child);} // remove all nodes after limit reached
else { // else if limit has not been reached
$words=explode(' ',$child->nodeValue); // create array of words in this node
$count=sizeof($words); // get number of words in this node
if ($word_count+$count>$limit) { // if addition of these words passes the limit
$words=implode(' ',array_slice($words,0,$limit-$word_count)); // create truncated
replacement content
$node->replaceChild($dom->createTextNode($words.'...'),$child); // swap in
replacement content
$limit_reached=true; // flag limit as reached
}
else $word_count+=$count; // else increment the word count and move on to the next node
};
}
else if ($child->hasChildNodes()) summarize($child,$limit); // else if non-text node with
children met, walk it recursively
$output=''; // init output
if (is_scalar($str)) { // if this is the first call
$xpath=new DOMXPath($dom); // create xpath object
foreach($xpath->query('//*[.="%removed_node%"]') as $empty_node)
$empty_node->parentNode->removeChild($empty_node); // remove all empty nodes
foreach($node->childNodes as $child) $output.=$dom->saveXML($child); // add remaining content
to output
unset($dom);
$limit_reached=false;
$word_count=0;
};
return $output;
}
----
Server IP: 64.71.164.2
Probable Submitter: 2002:4a42:e74d:0:21c:b3ff:feff:3d45
----
Manual Page -- http://www.php.net/manual/en/function.substr.php
Edit -- https://master.php.net/note/edit/88908
Del: integrated -- https://master.php.net/note/delete/88908/integrated
Del: useless -- https://master.php.net/note/delete/88908/useless
Del: bad code -- https://master.php.net/note/delete/88908/bad+code
Del: spam -- https://master.php.net/note/delete/88908/spam
Del: non-english -- https://master.php.net/note/delete/88908/non-english
Del: in docs -- https://master.php.net/note/delete/88908/in+docs
Del: other reasons-- https://master.php.net/note/delete/88908
Reject -- https://master.php.net/note/reject/88908
Search -- https://master.php.net/manage/user-notes.php