2010-12-07 54 views
1

我想将我的内容页面中的文本链接转换为使用php的活动链接。我尝试了所有可能的脚本,他们都很好,但他们转换img src标签中的链接的问题。他们转换链接无处不在,并破坏HTML代码。使用php自动链接创建而不破坏html标签

我发现一个很好的脚本,做我想要的东西,但它是在JavaScript中。它被称为jquery-linkify。 你可以在这里找到脚本 http://github.com/maranomynet/linkify/

脚本中的技巧,它转换文本链接而不破坏html代码。我试图将脚本转换为PHP,但失败了。

我不能在我的网站上使用脚本,因为有其他脚本与jQuery有冲突。

任何人都可以重写这个脚本为PHP?或者至少指导我如何?

谢谢。

+0

是否有任何特别的原因,为什么你不喜欢使用jQuery linkify? – 2010-12-07 06:22:31

+0

我不能在我的网站上使用jQuery linkify,因为有其他脚本(mootools)与jquery有冲突。 – alhoseany 2010-12-07 20:13:44

回答

1

首先,解析与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()去掉它们。

0

使用HTML parser并仅在文本节点内搜索URL。

+0

谢谢,我今天会试试这个,我希望它能正常工作。 – alhoseany 2010-12-07 20:14:27

0

我认为诀窍在于跟踪PHP代码中的单引号和双引号,并以正确的方式合并它们,以便将其放在内部,反之亦然。

例如,

<?PHP 

    //old html tags 
    echo "<h1>Header1</h1>"; 
    echo "<div>some text</div>"; 

    //your added links 
    echo "<p><a href='link1.php'>Link1</a><br>"; 
    echo "<a href='link1.php'>Link1</a></p>"; 

    //old html tags 
    echo "<h1>Another Header</h1>"; 
    echo "<div>some text</div>"; 

    ?> 

我希望这可以帮助你..

+0

我认为你是正确的报价。在jquery.linkify它使用这个正则表达式。 (?:(|:[:'(\ s] | <)(www \ .. +?\ .. +?)(?:(?:[:?] | \。+)?(?:\ s | $)| > | [)“',])/ g,' – alhoseany 2010-12-07 20:16:56

+0

在这个正则表达式中有双重和单一的qoutes。我不知道如何在正则表达式中将它们转义出来而不会破坏它们。 – alhoseany 2010-12-07 20:18:00

0
$text = 'Any text ... link http://example123.com and image <img src="http://exaple.com/image.jpg" />'; 
$text = preg_replace('!([^\"])(http:\/\/(?:[\w\.]+))([^\"])!', '\\1<a href="\\2">\\2</a>\\3', $text);