我正在拉入RSS提要,并使用DOMXPath将所有现有的锚标记转换为自定义标记,由于各种原因,它们看起来像这样:
[webserviceLink]{$url}[/webserviceLink][webserviceLinkName]{$text}[/webserviceLinkName]
这工作得很好,但我也想把所有非html文本链接转换为相同的格式,但我有一些问题。
下面是我转换文本链接的代码:$pattern = '(?xi)(?<![">])'b((?:https?://|www'd{0,3}[.]|[a-z0-9.'-]+[.][a-z]{2,4}/)(?:[^'s()<>]+|'(([^'s()<>]+|('([^'s()<>]+')))*'))+(?:'(([^'s()<>]+|('([^'s()<>]+')))*')|[^'s`!()'[']{};:''".,<>?«»“”‘’]))';
$desc = preg_replace_callback("#$pattern#i", function($matches)
{
$input = $matches[0];
$url = preg_match('!^https?://!i', $input) ? $input : "http://$input";
if (strlen($input) > 20 && !strpos($input, " "))
$input = substr($input, 0, 18)."... ";
return "[webserviceLink]{$url}[/webserviceLink][webserviceLinkName]{$input}[/webserviceLinkName]";
}, $desc);
我不知道如何在这个正则表达式中做负回调来检查我正在转换的链接是不是在现有的html标签中,如img,或在我的自定义链接标签上面。
我能够使用xpath使其工作。
$dom = new DOMDocument();
$dom->loadHTML(mb_convert_encoding($desc, 'HTML-ENTITIES', 'UTF-8'));
$xp = new DOMXPath($dom);
foreach ($xp->query('//text()[not(ancestor::a)]') as $node)
{
$pattern = '((?:https?://|www'd{0,3}[.]|[a-z0-9.'-]+[.][a-z]{2,4}/)(?:[^'s()<>]+|'(([^'s()<>]+|('([^'s()<>]+')))*'))+(?:'(([^'s()<>]+|('([^'s()<>]+')))*')|[^'s`!()'[']{};:''".,<>?«»“”‘’]))';
$replaced = preg_replace_callback("#$pattern#i", function($matches)
{
$input = $matches[0];
$url = preg_match('!^https?://!i', $input) ? $input : "http://$input";
if (strlen($input) > 20 && !strpos($input, " "))
$input = substr($input, 0, 18)."... ";
return "<a href='"{$url}'">{$input}</a>";
}, $node->wholeText);
$newNode = $dom->createDocumentFragment();
$newNode->appendXML($replaced);
$node->parentNode->replaceChild($newNode, $node);
}