2016-07-14 77 views
1

你好,我用这个方法用span标签PHP的DOMDocument跳过偶数元素

$string = clean($string); 
    $dom = new \DOMDocument; 
    $dom->loadHTML(mb_convert_encoding($string, 'HTML-ENTITIES', 'UTF-8'), LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD); 
    $iframes = $dom->getElementsByTagName('iframe'); 

    foreach($iframes as $iframe) { 
     $src = $iframe->getAttribute('src'); 
     $span = $dom->createElement('span'); 
     $span->setAttribute('title', $src); 
     $span->setAttribute('class', 'lazy-youtube'); 
     $iframe->parentNode->replaceChild($span, $iframe); 
    } 

    $images = $dom->getElementsByTagName('img'); 

    foreach($images as $image) { 
     $src = $image->getAttribute('src'); 
     $span = $dom->createElement('span'); 
     $span->setAttribute('title', $src); 
     $span->setAttribute('class', 'lazy-image'); 
     $image->parentNode->replaceChild($span, $image); 
    } 

    $html = $dom->saveHTML(); 

    return clean($html); 

全部更换iframe和IMG标签,但问题是,它跳过元素它总是这样

// Iframe 
<span> 
<iframe> 
<span> 
<iframe> 
<span> 
<iframe> 
<span> 
<iframe> 

// Img 
<span> 
<img> 
<span> 
<img> 
<span> 
<img> 
<span> 
<img> 

HTML代码中的I帧

<div class="content"> 
<p> 
    <iframe frameborder="0" height="315" src="https://www.youtube.com/embed/T6kG5vuPVSs?rel=0" width="560"></iframe> 
<p> 
</p> 
    <iframe frameborder="0" height="315" src="https://www.youtube.com/embed/GjnadPBMJGs?rel=0" width="560"></iframe> 
<p> 
</p> 
    <iframe frameborder="0" height="315" src="https://www.youtube.com/embed/KYm8SLLQ0kk?rel=0" width="560"></iframe> 
<p> 
</p> 
    <iframe frameborder="0" height="315" src="https://www.youtube.com/embed/xUVz4nRmxn4?rel=0" width="560"></iframe> 
<p> 
</p> 
    <iframe frameborder="0" height="315" src="https://www.youtube.com/embed/hmZ6ziQJByY?rel=0" width="560"></iframe> 
</p> 
</div> 

所有相同类型的元素具有相同的属性,唯一的SRC是不同的。任何人都知道我该如何解决它以取代所有元素?

+0

可能当您更换元素时,数组/对象会发生变化,将剩余的点移动到一个点上,然后滑动下一个点。这就是为什么我认为它跳过了。 – FirstOne

+0

@FirstOne,我该如何解决这个问题? – allyfai

+0

@FirstOne在数据库中存储html时使用这种方法,效率不高,你的意思是,它不会一直工作,或者它需要大量的时间来渲染它? – allyfai

回答

1

说明问题:它可能会跳过所有其他元素,因为一旦您删除iframe,例如,对象(元素列表)将以所有其他iframe转移到ocuppy被删除的位置的方式进行更改。

一个办法修复它:

// code 
$iframes = $dom->getElementsByTagName('iframe'); 
while($iframes->length > 0){ // while there are still frames left to change 
    foreach($iframes as $iframe) { 
     // your regular code to replace iframe with span 
     // break; // this makes it easier to understand, but not really necessary 
    } 
    $iframes = $dom->getElementsByTagName('iframe'); // get the (remaining) skipped frames until there is none left 
} 
// code 

不要忘了做同样的图像。



这里是一个更好的方式来理解这个问题:

 
1 - List of iframes 
iframe1 iframe2 iframe3 iframe4 iframe5 [...] 
    /\ - current item in loop 

2 - Replacing iframe1, it comes out of the list (since I just want iframes), so the list is now: 
iframe2 iframe3 iframe4 iframe5 [...] 
    /\ 

3 - Loop continues and it goes to the next item 
iframe2 iframe3 iframe4 iframe5 [...] 
      /\ - current item in loop 

见怎么样,这样一来,它会跳过所有其他元素?

+0

如果您获取DOMNodeList项目,则无需获取剩余的跳过框架。在下面检查我的答案。 –

0

发生这种情况是因为foreach没有创建迭代对象的副本,并且在替换子级时DOMNodeList元素得到修改。 迭代的DOMNodeList的正确的方法是:

$elements = $domElement->getElementsByTagName("iframe"); 
while($elements->length > 0) { 
    $oldNode = $elements->item(0); 
    $newNode = $dom->createElement("image"); 
    $oldNode->parentNode->replaceChild($oldNode, $newNode); 
} 

使用相同的逻辑,如果你需要从旧节点的子元素移动到新的一个,你可以这样做:

while($oldNode->childNodes->length > 0) 
    $newNode->appendChild($oldNode->childNodes->item(0));