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<b>a"a'a</b> a<b>a"a'a</b> a<b>a\"a\'a<\/b>