微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

php – 忽略preg_replace中的html标签

如何忽略此preg_replace中的html标记.
我有搜索的foreach函数,所以如果有人搜索“apple span”,preg_replace也会对span和html中断应用跨度:

preg_replace("/($keyword)/i","

提前致谢!

最佳答案
我假设您应该基于DOMDocument和DOMXPath而不是使用正则表达式来创建函数.即使那些功能非常强大,您也遇到了一些问题,例如您所描述的问题,这些问题并非(总是)通过正则表达式来解决.

一般说法是:不要用正则表达式解析HTML.

记住这一点是一个很好的规则,虽然它与任何规则一样,并不总是适用,但值得一提的是.

XPath允许您查找仅包含文本中所有搜索项的所有文本,忽略所有XML元素.

然后你只需要将这些文本包装到< span>你完成了

编辑:最后一些代码;)

首先,它使用xpath来定位包含搜索文本的元素.我的查询看起来像这样,这可能写得更好,我不是超级xpath pro:

'//*[contains(.,"'.$search.'")]/*[FALSE = contains(.,"'.$search.'")]/..'

$search包含要搜索的文本,不包含任何“(引用)字符(这会破坏它,如果需要引号,请参阅Cleaning/sanitizing xpath attributes以获得解决方法).

查询将返回包含文本节点的所有父节点,这些节点组合在一起将是包含搜索词的字符串.

因为这样的列表不容易进一步处理,我创建了一个表示DOMText节点列表的TextRange类.在文本节点列表上执行字符串操作非常有用,就好像它们是一个字符串一样.

这是例程的基本框架:

$str = '...'; # some XML

$search = 'text that span';

printf("Searching for: (%d) '%s'\n",strlen($search),$search);

$doc = new DOMDocument;
$doc->loadXML($str);
$xp = new DOMXPath($doc);

$anchor = $doc->getElementsByTagName('body')->item(0);
if (!$anchor)
{
    throw new Exception('Anchor element not found.');
}

// search elements that contain the search-text
$r = $xp->query('//*[contains(.,"'.$search.'")]/..',$anchor);
if (!$r)
{
    throw new Exception('XPath Failed.');
}

// process search results
foreach($r as $i => $node)
{   
    $textNodes = $xp->query('.//child::text()',$node);

    // extract $search textnode ranges,create fitting nodes if necessary
    $range = new TextRange($textNodes);        
    $ranges = array();
    while(FALSE !== $start = strpos($range,$search))
    {
        $base = $range->split($start);
        $range = $base->split(strlen($search));
        $ranges[] = $base;
    };

    // wrap every each matching textnode
    foreach($ranges as $range)
    {
        foreach($range->getNodes() as $node)
        {
            $span = $doc->createElement('span');
            $span->setAttribute('class','search_hightlight');
            $node = $node->parentNode->replaceChild($span,$node);
            $span->appendChild($node);
        }
    }
}

对于我的示例XML:

它产生以下结果:

这表明这甚至允许查找分布在多个标签上的文本.对于正则表达式来说,这并不容易.

你可以在这里找到完整的代码http://codepad.viper-7.com/U4bxbe(包括我从答案示例中取出的TextRange类).

由于该网站使用的旧版LIBXML版本,它在viper键盘上无法正常工作.它适用于我的LIBXML版本20707.我创建了一个关于此问题的相关问题:XPath query result order.

警告提示:此示例使用二进制字符串搜索(strpos)和用于使用DOMText::splitText函数拆分文本节点的相关偏移量.这可能导致错误的偏移,因为函数需要UTF-8字符偏移.正确的方法是使用mb_strpos获取基于UTF-8的值.

该示例仍然可行,因为它仅使用US-ASCII,其具有与示例数据相同的UTF-8偏移量.

对于现实生活情况,$search字符串应该是UTF-8编码的,应该使用mb_strpos而不是strpos:

 while(FALSE !== $start = mb_strpos($range,$search,'UTF-8'))

原文地址:https://www.jb51.cc/html/425804.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐