inamenaiの日記 RSSフィード

2009年03月14日

textContentとinnerHTML

Google検索後のページで検索ワードをハイライト表示するGreasemonkeyスクリプトを作ってたときに引っかかったことのメモ。

innerHTML
要素のマークアップと内容を取得・設定します。
textContent
要素とそのすべての子孫要素のテキスト内容を取得・設定します。
element - MDN

HTMLElementから値を取得するときの両者の主な違いは内容にHTMLマークアップを含むかどうかという点ですが、もう一つ、取得内容にエンコードされた特殊文字が含まれる場合も両者に違いがでてきます。ソース上に書かれた「&lt;b&gt;foo&lt;/b&gt;」というテキスト(画面上には「<b>foo</b>」と表示される)を取得するとき、innerHTMLはそのまま「&lt;b&gt;foo&lt;/b&gt;」が取得されるのに対して、textContentは画面上に表示される「<b>foo</b>」が取得されてきます。なので、textContentで取得した値をinnerHTMLにそのまま設定するとエスケープされていたはずの特殊文字が元に戻ってしまいます。

<p id="input">&lt;b&gt;foo&lt;/b&gt;</p>
<p id="output"></p>

<script type="text/javascript">
    var input = document.getElementById("input");
    var output = document.getElementById("output");

    var innerHTML = input.innerHTML;
    alert(innerHTML);  // 「&lt;b&gt;foo&lt;/b&gt;」
    var textContent = input.textContent;
    alert(textContent);  // 「<b>foo</b>」

    output.innerHTML = textContent;  // 太字の「foo」が画面に表示される!


    // ちなみに、テキストノードのnodeValueから取得する場合もtextContentと同じ挙動になります。
    var nodeValue = input.firstChild.nodeValue;
    alert(nodeValue);  // 「<b>foo</b>」
</script>

よくありそうな例としては、「画面のテキストの一部をtextContentやテキストノードのnodeValueから取得して、その内部や前後にタグを文字列で書き込んだあとに最後にinnerHTMLに渡してElementに変換する」という処理をすることがあります。このときに取得するテキストにエンコードされた「&lt;」や「&gt;」が含まれていた場合は、取得時に「<」や「>」に戻ってしまっているので再度エンコードし直してやる必要があります。これを忘れると場合によってはXSS脆弱性にもなりかねないので注意!

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証

トラックバック - http://d.hatena.ne.jp/inamenai/20090314/p1