2013-04-10 5 views
9

私は@Alex's approach hereを使用して、組み込みのDOMDocumentを使用してHTML文書からスクリプトタグを削除しました。問題は、Javascriptのコンテンツを含むスクリプトタグがあり、その後に外部のJavascriptソースファイルにリンクする別のスクリプトタグがあり、すべてのスクリプトタグがHTMLから削除されていない場合です。DOMDocumentはHTMLソースからスクリプトタグを削除します

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

上記のコードの出力:

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

あなたは出力から見ることができるように、唯一の外部スクリプトタグを削除しました。すべてのスクリプトタグが削除されていることを確認するためにできることはありますか?

答えて

19

あなたのエラーは実際には些細なことです。 A DOMNodeオブジェクト(およびすべての子孫 - DOMElementDOMNodeListなど)は、親要素が変更されたときに自動的に更新されます。これはPHPドキュメントの2行で書かれていますが、ほとんどがカーペットの下を掃除されています。

($k instanceof DOMNode)->lengthを使用してループし、その後ノードから要素を削除すると、lengthプロパティが実際に変更されます。私はこれと他のいくつかの癖に対抗するために私自身の図書館を書く必要がありました。

ソリューション:私は実際にループしていないよ

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

- ジャストインタイムで最初の要素1を飛び出ます。結果:http://sebrenauld.co.uk/domremovescript.php

+0

これはうまくいった、ありがとう! – RandomCoder

+6

もう1つの解決策は、要素を逆順にループすることです。 – CBroe

4

あなたはライブノードリストの驚き得ることを避けるために - あなたは、ノードを削除すると短くなる - あなたはiterator_to_arrayを使用して配列にコピーして仕事ができる:

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

素晴らしいです、ありがとうございます。 – Jonathan

+0

+1は、受け入れられた答えよりはるかに単純です - ノードリストで 'iterator_to_array()'を使うのは、文書を走査して変更を加えるときには、基本的に必須です。 –

関連する問題