特定のタグに特定の属性を設定する
seasar-user MLにて、Teedaで<input>と<textarea>にlang="ja"という属性を自動的に付加するような方法はないか?という質問が出ていたのでYmirではどうするのか考えてみた。
Ymir(というかYmirのZPTね)では、org.seasar.ymir.zpt.TemplateParsingInterceptorというインタフェースが用意されている。これの実装クラスを作成することで、ZPTのパース処理をインターセプトして、パース結果に手を入れることができるようになる。
<input>と<textarea>にlang="ja"という属性を自動的に付加するには、以下のようなクラスを作成して、app.diconにコンポーネント登録しておけば良い:
public class LangInterceptor implements TemplateParsingInterceptor { private static final String[] SPECIALATTRIBUTEPATTERNSTRINGS = new String[0]; private static final String[] SPECIALTAGPATTERNSTRINGS = new String[] { "input", "textarea" }; public String[] getSpecialAttributePatternStrings() { return SPECIALATTRIBUTEPATTERNSTRINGS; } public String[] getSpecialTagPatternStrings() { return SPECIALTAGPATTERNSTRINGS; } public Element[] tagElementCreated(TagElement tagElement, TemplateParsingInterceptorChain chain) { List<Attribute> attributeList = new ArrayList<Attribute>(Arrays .asList(tagElement.getAttributes())); attributeList.add(new Attribute("lang", "ja", "\"")); return new Element[] { new TagElement(tagElement.getName(), attributeList.toArray(new Attribute[0]), tagElement .getBodyElements()) }; } }
getSpecialTagPatternStringsメソッドでnew String[] { "input", "textarea" }を返すことで、<input>と<textarea>が見つかった場合だけtagElementCreatedメソッドが呼び出されるようにしている。
tagElementCreatedメソッドでは、lang="ja"属性を表すAttributeオブジェクトを生成し、受け取ったパース済みのTagElementオブジェクトの属性に追加する形で新しいTagElementオブジェクトを作って返すようにしている。これで全ての<input>と<textarea>にlang="ja"属性が追加される。