htmlcss HTML ソースのエスケープ処理

2015年4月19日

HTML ソースをページに表示させる際、そのままソースを記述してしまうと、HTML 要素として解釈されてしまうので、「< 」や「 >」 は変換(エスケープ)しておく必要があるが、いちいち変換するのは面倒なので一括して変換する方法のメモ。

目次

概要

テキストエリアに入力した HTML ソースをボタンをクリックすると、エスケープ処理(変換)した文字列を表示するページを作成。

HTML ソースのエスケープ処理用ページの作成

HTML

HTML の構造は以下の部分から成り、単純なもの。

  • textarea 要素(id=”input”):ソースを入力する部分
  • button 要素(id=”convert” と id=”clear”):変換または内容をクリアするためのボタン
  • pre 要素(id=”escapeHTML”):エスケープ処理(変換)された文字列を表示する部分
<body>
<div id="content">
  <h1>変換(エスケープ)処理</h1>
  <p>HTML ソースを入力</p>
  <div>
    <textarea id="input" rows="10" cols="60">
    </textarea>
  </div>
  <button id="convert">変換</button>
  <button id="clear">クリア</button>
  <div>
    <pre id="escapeHTML"></pre>
  </div>
</div>

jQuery

jQuery を使って処理を記述するので、body の閉じタグの直前等で jQuery を読み込む。

<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>

その後に以下の処理を記述。

<script>
jQuery(function($){  
    $('#convert').click(function() {
        var converted = $('#input').val().replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
        $('#escapeHTML').text(converted);
    });  
  
    $('#clear').click(function() {
        $('#input').val('');  
        $('#escapeHTML').text('');
    });      
});
</script>
</body>
  • エスケープ対象の文字は「<」「>」に加えて「”」「’」「&」の計5つ。
  • textarea 要素(id=”input”)に入力された文字列は $(‘#input’).val() で取得できる。
  • これらを replace() メソッドを使ってそれぞれ「&lt;」「&gt;」「&quot;」「&#39;」「&amp;」(文字参照)に変換。
  • 変換する際の順番は、最初に「&」を変換する(全ての文字参照に「&」が含まれているため)。

button 要素(id=”convert”)のクリックイベントで、変換した文字列を変数「converted」に格納して、それらを pre 要素(id=”escapeHTML”)のテキストとして表示。

また、button 要素(id=”clear”)のクリックイベントで、内容をクリア(空文字を代入)。

replace() メソッド

書式

replace(regexp, replacement)

引数
regexp :置換のパターンを表す RegExp オブジェクト。
replacement :置換テキストを表す文字列。
戻り値
最初またはすべてのマッチングで置換された新しい文字列。
  • replace() メソッドは文字列に対して検索と置換を行う。
  • 文字列で regexp にマッチするサブストリングを探し、replacement でそれらを置換する。
  • グローバル検索の g 属性が設定された regexp の場合は、replace() メソッドはすべてのマッチするサブストリングを置換する。
  • g 属性が設定されていない場合は、最初にマッチするサブストリングのみを置換する。
  • ドル記号($)は replacement 文字列では特殊な意味を持つ。

jQuery 部分の書き換え

jQuery の部分は、配列と for 文を使って以下のように記述ことも可能。

<script>
jQuery(function($){	
    var targets = ["&", "<", ">" ,'"', "'"];
    var escapes = ["&amp;", "&lt;", "&gt;", "&quot;", "&#39;"];

    $('#convert').click(function() {
        var converted = $('#input').val();
        for(var i=0; i<targets.length; i++){ 		 
            converted = converted.replace(new RegExp(targets[i], 'g'), escapes[i]);
        }		
        $('#escapeHTML').text(converted);
    });	
	
    $('#clear').click(function() {
        $('#input').val('');	
        $('#escapeHTML').text('');
    });			
});
</script>
  • 配列 targets に置換のパターンを記述
  • 配列 escapes に置換テキストを表す文字列を記述
    (順番は対応するように配置)
  • for 文を使って順番に replace() メソッドを実行

for 文を使って順番に replace() メソッドを実行する際に、注意する点としては replace() メソッドの第一引数が「RegExp オブジェクト」であるということ。

以下のように記述すると、思い通りにならない。

for(var i=0; i<targets.length; i++){ 		 
    converted = converted.replace(/targets[i]/, 'g'), escapes[i]);
}
または
for(var i=0; i<targets.length; i++){ 	
    var target = '/' + 	targets[i] + '/';
    converted = converted.replace(target, 'g'), escapes[i]);
}

「/」と「/」で囲まれたパターン文字列の中に変数を使いたい場合は、new RegExp を使って正規表現オブジェクトを生成するようにする。

for(var i=0; i<targets.length; i++){ 	
    var target = new RegExp(targets[i], 'g'); 
    converted = converted.replace(target, escapes[i]);
}	

正規表現(オブジェクト)は以下の 2 つの方法で作ることが可能。

参考:
正規表現 – JavaScript | MDN
RegExp – JavaScript | MDN

1.正規表現リテラルを使用する

var re = /abc/;

正規表現リテラルでは、スクリプトが評価されるときにその正規表現をコンパイルする。正規表現を定数として残しておくときは、この方法を使用するとよいパフォーマンスが得られる。

2.RegExp オブジェクトのコンストラクタ関数を呼び出す

var re = new RegExp("abc");

コンストラクタ関数を使用すると、実行時にその正規表現をコンパイルする。正規表現パターンが変わることがわかっている場合や、パターンがわからない場合、ユーザが入力するなど別のソースからパターンを取得する場合は、コンストラクタ関数を使用する。(変数を使用する場合)

サンプル

以下は、ローカル環境で使用するのを前提としたサンプル。

convert.html

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>変換(エスケープ)処理</title>
<style>
#content {
  margin: 20px auto;
  width: 100%;
  max-width: 900px;
}
h1 {
  font-size: 20px;
}
textarea {
  width: 95%;
  margin: 10px auto;
}
#escapeHTML {
  width: 95%;
  border: 1px solid #ccc;
  border-radius: 4px;
  padding: 10px;
  display: none;
  background-color: #efefef;
  font-family:"Lucida Console", Monaco, monospace;
  white-space: pre-wrap;
  overflow: auto;
}
#clear_all, #clear_escape {
  margin-right: 30px;
}
</style>
</head>
<body>
<div id="content">
  <h1>変換(エスケープ)処理</h1>
  <p>HTML ソースを入力</p>
  <div>
    <textarea id="input" rows="20" cols="60">
    </textarea>
  </div>
  <button id="convert">変換</button>
  <button id="clear_all">全てクリア</button>
  <button id="clear_html">HTML をクリア</button>
  <button id="clear_escape">出力をクリア</button>
  <button id="restore">リストア</button>
  <div>
    <pre id="escapeHTML"></pre>
  </div>
</div>
<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script> 
<script>
jQuery(function($){		
    var targets = ["&", "<", ">" ,'"', "'"];
    var escapes = ["&amp;", "&lt;", "&gt;", "&quot;", "&#39;"];
    var restore_input = '';
    var restore_escape = '';

    $('#convert').click(function() {
        var converted = $('#input').val();
        restore_input = converted;
        for(var i=0; i<targets.length; i++){ 		 
            converted = converted.replace(new RegExp(targets[i], 'g'), escapes[i]);
        }	
        restore_escape = converted;	
        $('#escapeHTML').text(converted).css('display', 'block');
    });	
	
    $('#clear_html').click(function() {
        $('#input').val('');	
    });	
    
    $('#clear_escape').click(function() {
        $('#escapeHTML').text('').css('display', 'none');
    });	
	
    $('#clear_all').click(function() {
        $('#input').val('');	
        $('#escapeHTML').text('').css('display', 'none');
    });		
    
    $('#restore').click(function() {
        $('#input').val(restore_input);	
        $('#escapeHTML').text(restore_escape).css('display', 'block');
    });				
});
</script>
</body>
</html>