PHP Token replaces html entities
I want to make certain words/strings like links if found in the text. I have a piece of code from php.bet which does that, but it also removes the beginning and end of tags from <a href="http://www.domain.com/index.php" title="Home">go to homepage</a>
. Can you help solve this?
Here's the piece of code:
<?php
$str_in = '<p>Hi there worm! You have a disease!</p><a href="http://www.domain.com/index.php" title="Home">go to homepage</a>';
$replaces= array(
'worm' => 'http://www.domain.com/index.php/worm.html',
'disease' => 'http://www.domain.com/index.php/disease.html'
);
function addLinks($str_in, $replaces)
{
$str_out = '';
$tok = strtok($str_in, '<>');
$must_replace = (substr($str_in, 0, 1) !== '<');
while ($tok !== false) {
if ($must_replace) {
foreach ($replaces as $tag => $href) {
if (preg_match('/\b' . $tag . '\b/i', $tok)) {
$tok = preg_replace(
'/\b(' . $tag . ')\b/i',
'<a title="' . $tag . '" href="' . $href . '">\1</a>',
$tok,
1);
unset($replaces[$tag]);
}
}
} else {
$tok = "<$tok>";
}
开发者_StackOverflow社区 $str_out .= $tok;
$tok = strtok('<>');
$must_replace = !$must_replace;
}
return $str_out;
}
echo addLinks($str_in, $replaces);
The result is:
Hi there worm! You have a disease!
a href="http://www.domain.com/index.php" title="Home"/a
The "worm" and "disease" words are transformed into links like desired, but the rest...
Thanks a lot!
This pair of functions should do what you want without the problems that come with parsing HTML with regex or str_replace
.
function process($node, $replaceRules)
{
if($node->hasChildNodes()) {
$nodes = array();
foreach ($node->childNodes as $childNode) {
$nodes[] = $childNode;
}
foreach ($nodes as $childNode) {
if ($childNode instanceof DOMText) {
$text = preg_replace(
array_keys($replaceRules),
array_values($replaceRules),
$childNode->wholeText);
$node->replaceChild(new DOMText($text),$childNode);
}
else {
process($childNode, $replaceRules);
}
}
}
}
function addLinks($str_in, $replaces)
{
$replaceRules = array();
foreach($replaces as $k=>$v) {
$k = '/\b(' . $k . ')\b/i';
$v = '<a href="' . $v . '">$1</a>';
$replaceRules[$k] = $v;
}
$doc = new DOMDocument;
$doc->loadHTML($str_in);
process($doc->documentElement, $replaceRules);
return html_entity_decode($doc->saveHTML());
}
Note: No need to worry if the HTML is not well structured (as in your example); however, the output will be well structured.
Credit where it’s due:
The recursive process()
function, which does most of the real work, comes direclty from Lukáš Lalinský’s answer to How to replace text in HTML. The addLinks()
function is just a use case tailored to fit your question.
Not sure why you've got that large construction, when something like:
$str_out = preg_replace('/(' . preg_quote(implode('|', array_keys($replaces))) . ')/', $replaces[$1], $str_in);
would accomplish about the same thing. Of course, using regexes to process HTML is a hazardous process. You should use DOM with some xpath to do this more reliably.
精彩评论