【问题标题】:Wrap DOM element in another DOM element in PHP在 PHP 中将 DOM 元素包装在另一个 DOM 元素中
【发布时间】:2011-04-01 06:23:26
【问题描述】:

我最初使用 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 行中的数据过早结束/untitled_3xd..php 第 24 行
PHP 警告:DOMDocumentFragment::appendXML(): Image Link in /private/var/folders/78/78vHGigZHcuFeXB1KKJSb++++TI/-Tmp-/untitled_3xd..php 在第 24 行 PHP 警告:DOMDocumentFragment::appendXML(): ^ in /private/var/folders/78/78vHGigZHcuFeXB1KKJSb++++TI/-Tmp-/untitled_3xd..php 在第 24 行 PHP 警告:DOMNode::appendChild(): Document Fragment is empty in /private/var/folders/78/78vHGigZHcuFeXB1KKJSb++++TI/-Tmp-/untitled_3xd..php on line 25

<!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>

这主要是有效的,除了它真的很挑剔,如果a href 中有一个img(或类似的)标签,你可以看到它死了。

完成这项工作的最佳方法是什么。我已经很尴尬地撞了头。

编辑

根据下面的反馈,这里是修改后的代码和输出。请注意,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>

【问题讨论】:

    标签: php html dom


    【解决方案1】:

    这是很好的信息,很抱歉这么晚才参加聚会,但对我来说有一个错误......最后:

    $tag->appendChild($child);
    

    应该是

    $tag->appendChild($element);
    

    这是我可以让它工作的唯一方法。

    【讨论】:

      【解决方案2】:

      为什么要重新创建节点?为什么不直接更换节点? (如果我明白你想要做什么)......

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

      【讨论】:

      • 谢谢,效果非常好。请参阅上面的已编辑 OP。对于带有 &lt;img /&gt; 标记的链接,文本不会被包裹在新的 &lt;span&gt; 中,而只是 &lt;img /&gt;
      猜你喜欢
      • 1970-01-01
      • 2014-09-30
      • 2011-06-12
      • 2013-07-20
      • 2018-11-27
      • 1970-01-01
      • 1970-01-01
      • 2012-04-17
      • 1970-01-01
      相关资源
      最近更新 更多