2010-09-13 57 views
1

我正在处理的网站有一个填充词汇表术语的数据库表。我正在构建一个函数,它将采用一些HTML并用工具提示链接替换词汇表术语的第一个实例。将多个链接插入文本,忽略偶然发生的匹配

虽然我遇到了问题。由于它不仅仅是一个替换,该功能正在取代之前迭代中插入的文本,因此HTML被取消了。

我猜的底线是,我需要忽略的文本,如果它:

  • 出现<和所有的HTML标签的>,或
  • <a></a>标签的文本中出现内。

这是我到目前为止。我希望有人会有一个聪明的解决方案。

function insertGlossaryLinks($html) 
{ 
    // Get glossary terms from database, once per request 
    static $terms; 
    if (is_null($terms)) { 
     $query = Doctrine_Query::create() 
      ->select('gt.title, gt.alternate_spellings, gt.description') 
      ->from('GlossaryTerm gt'); 
     $glossaryTerms = $query->rows(); 

     // Create whole list in $terms, including alternate spellings 
     $terms = array(); 
     foreach ($glossaryTerms as $glossaryTerm) { 

      // Initialize with title 
      $term = array(
       'wordsHtml' => array(
        h(trim($glossaryTerm['title'])) 
        ), 
       'descriptionHtml' => h($glossaryTerm['description']) 
       ); 

      // Add alternate spellings 
      foreach (explode(',', $glossaryTerm['alternate_spellings']) as $alternateSpelling) { 
       $alternateSpelling = h(trim($alternateSpelling)); 
       if (empty($alternateSpelling)) { 
        continue; 
       } 
       $term['wordsHtml'][] = $alternateSpelling; 
      } 

      $terms[] = $term; 
     } 
    } 

    // Do replacements on this HTML 
    $newHtml = $html; 
    foreach ($terms as $term) { 
     $callback = create_function('$m', 'return \'<a href="javascript:void(0);" class="glossary-term" title="'.$term['descriptionHtml'].'"><span>\'.$m[0].\'</span></a>\';'); 
     $term['wordsHtmlPreg'] = array_map('preg_quote', $term['wordsHtml']); 
     $pattern = '/\b('.implode('|', $term['wordsHtmlPreg']).')\b/i'; 
     $newHtml = preg_replace_callback($pattern, $callback, $newHtml, 1); 
    } 

    return $newHtml; 
} 

回答

0

我结束了使用preg_replace_callback用占位符替换所有现有的链接。然后我插入新的词汇表术语链接。然后我放回我已经取代的链接。

它工作的很棒!

1

使用Regexes来处理HTML总是风险很大的业务。您将花很长时间来处理您的Regexes的贪婪和懒惰,以仅捕获不在标签中的文本,而不是在标签名称本身中。我的建议是抛弃你当前使用的方法,并用HTML解析器解析你的HTML,就像这样:http://simplehtmldom.sourceforge.net/。我以前使用过它,并已推荐给其他人。这是处理复杂HTML的简单方法。

+0

我无法弄清楚你提到的这个库如何帮助我解决这个特定的问题。 – mattalxndr 2010-09-22 02:20:42

+0

你会用它来解析HTML并访问DOM。在那里,你可以明确地在DOM上执行你想要的操作。 – 2010-09-22 16:20:48