読者です 読者をやめる 読者になる 読者になる
無料で使えるシステムトレードフレームワーク「Jiji」 をリリースしました!

・OANDA Trade APIを利用した、オープンソースのシステムトレードフレームワークです。
・自分だけの取引アルゴリズムで、誰でも、いますぐ、かんたんに、自動取引を開始できます。

JavaScriptの文字列をエスケープする

$("#foo").text("${var}");

の場合、「${var}」に含まれるXMLエンティティはエスケープしなくていいとしても「"」や「'」は「\」でエスケープしないとJavaScript的にダメなんでは、と思ったらVelocityにちゃんと機能が用意されていましたよ、と。XMLエンティティのエスケープと同じ感じで「"org.apache.velocity.app.event.implement.EscapeJavaScriptReference"」を指定すれば埋め込み文字列をJavaScriptの文字列としてエスケープしてくれます。

final VelocityEngine engine = new VelocityEngine();
Properties p = new Properties();

// プロパティとして、JavaScript文字列のエスケープを行なうハンドラを指定
p.setProperty("eventhandler.referenceinsertion.class",
    "org.apache.velocity.app.event.implement.EscapeJavaScriptReference");
// エスケープを行なう変数名の指定も必要
p.setProperty( "eventhandler.escape.javascript.match", "/.*/" );
engine.init(p);

VelocityContext context = new VelocityContext();
context.put( "test", "a'a\"a\\a" ); // エスケープが必要な文字列
StringWriter sw = new StringWriter();
engine.evaluate( context, sw, "test", "$test" );

System.out.println( sw.toString() );

実行結果です。

a\'a\"a\\a

XMLエンティティのエスケープとJavaScript文字列のエスケープを両方行う。

プロパティで両方指定すればOK。Propertiesでは値をひとつしか持てないため、addProperty()メソッドを利用します。以下は、

  • 「_js_」で始まる変数 .. JavaScript文字列としてエスケープ
  • 「_」で始まる変数 .. 何もしない
  • その他 .. XMLエンティティをエスケープ

する例です。

final VelocityEngine engine = new VelocityEngine();
engine.addProperty("eventhandler.referenceinsertion.class",
"org.apache.velocity.app.event.implement.EscapeHtmlReference");
engine.addProperty("eventhandler.referenceinsertion.class",
"org.apache.velocity.app.event.implement.EscapeJavaScriptReference");
// 「_」で始まらない変数内のXMLエンティティをエスケープ
engine.setProperty( "eventhandler.escape.html.match", "/^\\$([^_\\{].*|\\{[^_].*\\})$/" );
// 「_js_」で始まる変数をJavaScript文字列としてエスケープ
engine.setProperty( "eventhandler.escape.javascript.match", "/^\\$\\{?_js_.*/" );
engine.init();

VelocityContext context = new VelocityContext();
context.put( "test", "a<b>a\"a'a</b>" ); 
context.put( "_test", "a<b>a\"a'a</b>" ); 
context.put( "_js_test", "a<b>a\"a'a</b>" ); 
StringWriter sw = new StringWriter();
engine.evaluate( context, sw, "test", "$test\n$_test\n$_js_test " );

System.out.println( sw.toString() );

実行結果です。

a&lt;b&gt;a&quot;a'a&lt;/b&gt;
a<b>a"a'a</b>
a<b>a\"a\'a<\/b>