2013-04-10 32 views
3

我的RSS拉动饲料和使用DOMXPath转换看起来像这样因各种原因所有现有的锚标签自定义标签:PHP:转换文本链接的锚标记

[webserviceLink]{$url}[/webserviceLink][webserviceLinkName]{$text}[/webserviceLinkName] 

这个伟大的工程,但我'd也喜欢将所有非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,或者在我上面的自定义链接标签中。

+0

你能提供一个输入/输出的例子吗? – Loamhoof 2013-04-10 14:34:02

+0

好吧,让自己的自定义链接标记通过是很容易的,因为您可以在行尾注释并在脚本中检查它。 现有的标签可以根据他们的列表进行检查,但IE和Chrome自定义标签可能会让这个错误检查成为婊子。 对所有您想要编辑的标签都更加安全,对它们运行代码,然后替换这些行。 – 2013-04-10 14:36:26

+0

请参阅:[如何替换文本网址并排除HTML标记中的网址?](http://stackoverflow.com/q/4003031/2261774) – 2013-04-10 23:46:16

回答

1

我能够使用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); 
    }