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;
}
4

2 回答 2

1

使用正则表达式处理 HTML 总是有风险的。您将花费很长时间摆弄正则表达式的贪婪和懒惰,只捕获不在标签中的文本,而不是在标签名称本身中。我的建议是放弃您当前使用的方法并使用 HTML 解析器解析您的 HTML,例如:http ://simplehtmldom.sourceforge.net/ 。我以前用过,也推荐给了其他人。这是处理复杂 HTML 的一种更简单的方法。

于 2010-09-13T21:40:27.500 回答
0

我最终使用 preg_replace_callback 将所有现有链接替换为占位符。然后我插入了新的词汇表术语链接。然后我放回我替换的链接。

它工作得很好!

于 2010-09-22T02:22:07.027 回答