我最初使用Regex就这些问题提出了一个问题,但建议使用PHP DOM库代替......这是优越的,但我仍然卡住了。
基本上,我想在<a>
中包含<span>
的内容,如果它尚未包含在<span>
中。
<?php
$input = <<<EOT
<html><head></head>
<body bgcolor="#393a36">
<a href="#"><span style="color:#ffffff;">Link 1</span></a>
<a href="#">Link 2</a>
<a href="#"><img src="mypic.gif" />Image Link</a>
<a href="#"><u>Underlined Link</u></a>
</body>
</html>
EOT;
$doc = new DOMDocument();
$doc->loadHTML($input);
$tags = $doc->getElementsByTagName('a');
foreach ($tags as $tag) {
$spancount = $tag->getElementsByTagName("span")->length;
if($spancount == 0){
$content = nodeContent($tag);
$element = $doc->createElement('span');
$element->setAttribute('style','color:#ffffff;');
$frag = $doc->createDocumentFragment();
$frag->appendXML($content);
$element->appendChild($frag);
$tag->nodeValue = ""; //clear node
$tag->appendChild($element);
}
}
echo $doc->saveHTML();
function nodeContent($n, $outer=false) {
$d = new DOMDocument('1.0');
$d->formatOutput = true;
$b = $d->importNode($n->cloneNode(true),true);
$d->appendChild($b);
$h = $d->saveHTML();
// remove outter tags
if (!$outer) $h = substr($h,strpos($h,'>')+1,-(strlen($n->nodeName)+4));
return $h;
}
它提供了这个输出:
PHP警告:DOMDocumentFragment :: appendXML():实体:第1行:解析器错误:/ private / var / folders / 78 / 78vHGigZHcuFeXB1KKJSb ++++ TI / -Tmp-中标记img第1行中数据的过早结束第24行的/untitled_3xd..php
PHP警告:DOMDocumentFragment :: appendXML():第24行的/private/var/folders/78/78vHGigZHcuFeXB1KKJSb++++TI--Tmp-/untitled_3xd..php中的图像链接 PHP警告:DOMDocumentFragment :: appendXML():^ in /private/var/folders/78/78vHGigZHcuFeXB1KKJSb++++TI/-Tmp-/untitled_3xd..php 24行 PHP警告:DOMNode :: appendChild():文档片段在第25行的/private/var/folders/78/78vHGigZHcuFeXB1KKJSb++++ TTI-/untitled_3xd..php中为空
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html>
<head></head>
<body bgcolor="#393a36">
<a href="#"><span style="color:#ffffff;">Link 1</span></a>
<a href="#"><span style="color:#ffffff;">Link 2</span></a>
<a href="#"><span style="color:#ffffff;"></span></a>
<a href="#"><span style="color:#ffffff;"><u>Underlined Link</u></span></a>
</body>
</html>
这主要是有效的,除非它非常挑剔,如果img
内有a href
(或类似)标记,你可以看到它会死掉。
使这项工作的最佳方法是什么。我现在一直在尴尬地争吵很长时间。
修改
根据以下反馈,这里是修改后的代码和输出。请注意,img
标记之前的文本由于某种原因未被包装。任何想法?
$doc = new DOMDocument();
$doc->loadHTML($input);
$tags = $doc->getElementsByTagName('a');
foreach ($tags as $tag) {
$spancount = $tag->getElementsByTagName("span")->length;
if($spancount == 0){
$element = $doc->createElement('span');
$element->setAttribute('style','color:#ffffff;');
foreach ($tag->childNodes as $child) {
$tag->removeChild($child);
$element->appendChild($child);
}
$tag->appendChild($element);
}
}
echo $doc->saveHTML();
输出:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html>
<head></head>
<body bgcolor="#393a36">
<a href="#"><span style="color:#ffffff;">Link 1</span></a>
<a href="#"><span style="color:#ffffff;">Link 2</span></a>
<a href="#">Image Link<span style="color:#ffffff;"><img src="mypic.gif"></span></a>
<a href="#"><span style="color:#ffffff;"><u>Underlined Link</u></span></a>
</body>
</html>
答案 0 :(得分:9)
为什么要重新创建节点呢?为什么不直接替换节点? (如果我理解你要做的事情)......
if($spancount == 0){
$element = $doc->createElement('span');
$element->setAttribute('style','color:#ffffff;');
$tag->parentNode->replaceChild($element, $tag);
$element->apendChild($tag);
}
修改哎呀,看起来你正试图将所有内容都包裹在$tag
的范围内......请尝试这样做:
if($spancount == 0){
$element = $doc->createElement('span');
$element->setAttribute('style','color:#ffffff;');
foreach ($tag->childNodes as $child) {
$tag->removeChild($child);
$element->appendChild($child);
}
$tag->appendChild($child);
}
Edit2 根据您的搜索结果,由于删除了节点,看起来foreach没有完成...尝试用此替换foreach:
while ($tag->childNodes->length > 0) {
$child = $tag->childNodes->item(0);
$tag->removeChild($child);
$element->appendChild($child);
}
答案 1 :(得分:1)
这是一个很好的信息,很抱歉这么晚才进入聚会,但最后还有一个错误......最后:
$tag->appendChild($child);
应该是
$tag->appendChild($element);
这是我能让它发挥作用的唯一方法。