如何查找html文件内容替换,如何替换文本URL并在HTML标签中排除URL?

您不应该使用正则表达式-至少不是仅使用正则表达式。请使用适当的HTML DOM解析器,例如PHP的DOM库之一。然后,您可以迭代节点,检查它是否是文本节点,然后进行正则表达式搜索并适当地替换文本节点。

这样的事情应该做到:

$pattern = "~((?:http|https|ftp)://(?:\S*?\.\S*?))(?=\s|\;|\)|\]|\[|\{|\}|,|\"|'|:|\

$doc = new DOMDocument();

$doc->loadHTML($str);

// for every element in the document

foreach ($doc->getElementsByTagName('*') as $elem) {

// for every child node in each element

foreach ($elem->childNodes as $node) {

if ($node->nodeType === XML_TEXT_NODE) {

// split the text content to get an array of 1+2*n elements for n URLs in it

$parts = preg_split($pattern, $node->nodeValue, -1, PREG_SPLIT_DELIM_CAPTURE);

$n = count($parts);

if ($n > 1) {

$parentNode = $node->parentNode;

// insert for each pair of non-URL/URL parts one DOMText and DOMElement node before the original DOMText node

for ($i=1; $i

$a = $doc->createElement('a');

$a->setAttribute('href', $parts[$i]);

$a->setAttribute('target', '_blank');

$a->appendChild($doc->createTextNode($parts[$i]));

$parentNode->insertBefore($doc->createTextNode($parts[$i-1]), $node);

$parentNode->insertBefore($a, $node);

}

// insert the last part before the original DOMText node

$parentNode->insertBefore($doc->createTextNode($parts[$i-1]), $node);

// remove the original DOMText node

$node->parentNode->removeChild($node);

}

}

}

}

好了,因为的DOMNodeList小号的getElementsByTagName和childNodes是活的,在DOM的每一个变化反映到该列表中,因此你不能用foreach那会也迭代新加入的节点。取而代之的是,您需要使用for循环,并跟踪添加的元素以增加索引指针,并最好适当地预先计算数组边界。

但是由于在这种复杂的算法中这非常困难(三个for循环中的每个循环都需要一个索引指针和数组边界),因此使用递归算法会更方便:

function mapOntoTextNodes(DOMNode $node, $callback) {

if ($node->nodeType === XML_TEXT_NODE) {

return $callback($node);

}

for ($i=0, $n=count($node->childNodes); $i

$nodesChanged = 0;

switch ($node->childNodes->item($i)->nodeType) {

case XML_ELEMENT_NODE:

$nodesChanged = mapOntoTextNodes($node->childNodes->item($i), $callback);

break;

case XML_TEXT_NODE:

$nodesChanged = $callback($node->childNodes->item($i));

break;

}

if ($nodesChanged !== 0) {

$n += $nodesChanged;

$i += $nodesChanged;

}

}

}

function foo(DOMText $node) {

$pattern = "~((?:http|https|ftp)://(?:\S*?\.\S*?))(?=\s|\;|\)|\]|\[|\{|\}|,|\"|'|:|\

$parts = preg_split($pattern, $node->nodeValue, -1, PREG_SPLIT_DELIM_CAPTURE);

$n = count($parts);

if ($n > 1) {

$parentNode = $node->parentNode;

$doc = $node->ownerDocument;

for ($i=1; $i

$a = $doc->createElement('a');

$a->setAttribute('href', $parts[$i]);

$a->setAttribute('target', '_blank');

$a->appendChild($doc->createTextNode($parts[$i]));

$parentNode->insertBefore($doc->createTextNode($parts[$i-1]), $node);

$parentNode->insertBefore($a, $node);

}

$parentNode->insertBefore($doc->createTextNode($parts[$i-1]), $node);

$parentNode->removeChild($node);

}

return $n-1;

}

$str = '

sometext http://www.somedomain.com/index.html sometext image.jpg sometext sometext
';

$doc = new DOMDocument();

$doc->loadHTML($str);

$elems = $doc->getElementsByTagName('body');

mapOntoTextNodes($elems->item(0), 'foo');

这里mapOntoTextNodes用于将给定的回调函数映射到DOM文档中的每个DOMText节点上。您可以传递整个DOMDocument节点,也可以仅传递特定的DOMNode(在这种情况下,仅BODY传递该节点)。

该函数foo然后被用于查找和替换在平原网址一个DOMText通过分裂节点的内容的内容字符串转换成非URL / URL用部件preg_split,同时捕获造成的1 + 2的阵列所使用的分隔符· Ñ项目。然后,将非URL部分替换为新的DOMText节点,然后将URL部分替换为新A元素,然后将其插入到原始DOMText节点之前,然后将其最后删除。由于此操作是mapOntoTextNodes递归的,因此只需在特定的DOMNode上调用该函数即可。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值