我想使用 php 将内容页面中的文本链接转换为事件链接。我尝试了所有可能的脚本,它们都很好,但问题是它们转换 img src 标记中的链接。他们到处转换链接并破坏 html 代码。
我找到了一个很好的脚本,它可以完全满足我的要求,但它是用 javascript 编写的。它被称为 jquery-linkify。 你可以在这里找到脚本 http://github.com/maranomynet/linkify/
脚本中的技巧是在不破坏 html 代码的情况下转换文本链接。我尝试将脚本转换为 php 但失败了。
我无法在我的网站上使用该脚本,因为还有其他脚本与 jquery 冲突。
有人可以为 php 重写这个脚本吗?或者至少指导我如何做?
谢谢。
最佳答案
首先,使用 HTML 解析器解析文本,例如 DOMDocument::loadHTML
。请注意,糟糕的 HTML 可能很难解析,并且根据解析器的不同,运行此类函数后,您可能会在浏览器中得到略有不同的输出。
PHP 的 DOMDocument
在这方面不太灵活。使用其他工具解析可能会有更好的运气。但如果您正在使用有效的 HTML(并且您应该尝试这样做,如果它在您的控制范围内),那么这些都不是问题。
解析文本后,您需要查看文本节点中的链接并替换它们。使用正则表达式是最简单的方法。
这是一个执行此操作的示例脚本:
<?php
function linkify($text)
{
$re = "@\b(https?://)?(([0-9a-zA-Z_!~*'().&=+$%-]+:)?[0-9a-zA-Z_!~*'().&=+$%-]+\@)?(([0-9]{1,3}\.){3}[0-9]{1,3}|([0-9a-zA-Z_!~*'()-]+\.)*([0-9a-zA-Z][0-9a-zA-Z-]{0,61})?[0-9a-zA-Z]\.[a-zA-Z]{2,6})(:[0-9]{1,4})?((/[0-9a-zA-Z_!~*'().;?:\@&=+$,%#-]+)*/?)@";
preg_match_all($re, $text, $matches, PREG_OFFSET_CAPTURE);
$matches = $matches[0];
$i = count($matches);
while ($i--)
{
$url = $matches[$i][0];
if (!preg_match('@^https?://@', $url))
$url = 'http://'.$url;
$text = substr_replace($text, '<a href="'.$url.'">'.$matches[$i][0].'</a>', $matches[$i][1], strlen($matches[$i][0]));
}
return $text;
}
$dom = new DOMDocument();
$dom->loadHTML('<b>stackoverflow.com</b> <a href="stackoverflow.com">test</a>');
$xpath = new DOMXpath($dom);
foreach ($xpath->query('//text()') as $text)
{
$frag = $dom->createDocumentFragment();
$frag->appendXML(linkify($text->nodeValue));
$text->parentNode->replaceChild($frag, $text);
}
echo $dom->saveHTML();
?>
我没有想出那个正则表达式,我不能保证它的准确性。除了上述情况外,我也没有测试该脚本。但是,这应该足以让您继续前进。
输出:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html>
<body>
<b><a href="http://stackoverflow.com">stackoverflow.com</a></b>
<a href="stackoverflow.com">test</a>
</body>
</html>
请注意,saveHTML()
添加了周围的标签。如果这是一个问题,您可以使用 substr()
将它们删除。
关于php - 使用 php 自动创建链接而不破坏 html 标签,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4373927/