2013-04-10 11 views
9

Ich habe @Alex's approach here verwendet, um Skript-Tags aus einem HTML-Dokument mit dem integrierten DOMDocument zu entfernen. Das Problem ist, wenn ich ein Skript-Tag mit Javascript-Inhalt und dann ein anderes Skript-Tag, das auf eine externe Javascript-Quelldatei verweist, nicht alle Skript-Tags aus dem HTML entfernt sind.DOMDocument Skript-Tags aus der HTML-Quelle entfernen

$result = ' 
<!doctype html> 
<html> 
    <head> 
     <meta charset="utf-8"> 
     <title> 
      hey 
     </title> 
     <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script> 
     <script> 
      alert("hello"); 
     </script> 
    </head> 
    <body>hey</body> 
</html> 
'; 

$dom = new DOMDocument(); 
if($dom->loadHTML($result)) 
{ 
    $script_tags = $dom->getElementsByTagName('script'); 

    $length = $script_tags->length; 

    for ($i = 0; $i < $length; $i++) { 
     if(is_object($script_tags->item($i)->parentNode)) { 
      $script_tags->item($i)->parentNode->removeChild($script_tags->item($i)); 
     } 
    } 

    echo $dom->saveHTML(); 
} 

Die oben genannten Code-Ausgänge:

<html> 
    <head> 
     <meta charset="utf-8"> 
     <title>hey</title> 
     <script> 
     alert("hello"); 
     </script> 
    </head> 
    <body> 
     hey 
    </body> 
</html> 

Wie Sie aus der Ausgabe sehen können, nur der externe Script-Tag entfernt wurde. Kann ich irgendetwas tun, um sicherzustellen, dass alle Script-Tags entfernt werden?

Antwort

19

Ihr Fehler ist eigentlich trivial. Ein DOMNode Objekt (und alle seine Nachkommen - DOMElement, DOMNodeList und einige andere!) Wird automatisch aktualisiert, wenn sich das übergeordnete Element ändert, insbesondere wenn sich die Anzahl der untergeordneten Elemente ändert. Dies ist auf ein paar Zeilen im PHP-Dokument geschrieben, wird aber meistens unter den Teppich gekehrt.

Wenn Sie Schleife mit ($k instanceof DOMNode)->length, und anschließend Elemente aus den Knoten entfernen, werden Sie feststellen, dass die length Eigenschaft tatsächlich ändert! Ich musste meine eigene Bibliothek schreiben, um dem und einigen anderen Macken entgegenzuwirken.

Die Lösung:

if($dom->loadHTML($result)) 
{ 
    while (($r = $dom->getElementsByTagName("script")) && $r->length) { 
      $r->item(0)->parentNode->removeChild($r->item(0)); 
    } 
echo $dom->saveHTML(); 

Ich bin nicht wirklich Looping - nur einen nach dem anderen dem ersten Elemente knallen. Das Ergebnis: http://sebrenauld.co.uk/domremovescript.php

+0

Das hat funktioniert, danke! – RandomCoder

+6

Eine andere Lösung besteht darin, die Elemente in umgekehrter Reihenfolge zu durchlaufen. – CBroe

4

Um zu vermeiden, dass Sie die Überraschungen eines Live Knotenliste bekommen -, die kürzer als Sie bekommt Knoten löschen - Sie können mit einer Kopie in einem Array arbeiten iterator_to_array mit:

foreach(iterator_to_array($dom->getElementsByTagName($tag)) as $node) { 
    $node->parentNode->removeChild($node); 
}; 
+1

Fantastisch, danke. – Jonathan

+0

+1 viel einfacher als die akzeptierte Antwort - es scheint, dass die Verwendung von 'iterator_to_array()' auf Knotenlisten ist ein Muss, wenn Sie das Dokument durchlaufen, um Änderungen vorzunehmen. –