XML の DOCTYPE 宣言の文字列を構築するサンプル・コードのメモ。 DOCTYPE 宣言ってあんまりマジメに扱ったことないので、処理が間違ってる所もあるかも知れませんがご了承を。
公開識別子とシステム識別子のどちらもある場合
まずは、一番よく見る DOCTYPE 宣言(の1つ)である、「公開識別子 (public ID) とシステム識別子 (system ID) がある場合」に限定します。 具体的には、以下のような DOCTYPE 宣言を扱います:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.0//EN" "http://www.w3.org/TR/xhtml-basic/xhtml-basic10.dtd">
この DOCTYPE 宣言を構築するメソッドを toDTDString(..) として作成します。 このメソッドの引数と上記の DOCTYPE 宣言での値は下表のようになります:
変数名 | 値 | |
---|---|---|
要素名 | name | html |
公開識別子 | publicId | //W3C//DTD XHTML Basic 1.0//EN |
システム識別子 | systemId | http://www.w3.org/TR/xhtml-basic/xhtml-basic10.dtd |
String#format(..) メソッドを用いた実装はチョw簡単:
public static String toDtdString(String name, String publicId, String systemId){ return String.format( "<!DOCTYPE %s PUBLIC \"%s\" \"%s\">", name, publicId, systemId); }
上記の DOCTYPE 宣言のサンプルのような改行は入ってませんが、気にせずに。
公開識別子、システム識別子が null や空でも扱えるようにする
「公開識別子とシステム識別子のどちらもある場合」以外にも、公開識別子やシステム識別子がない場合もよくあるので、それらも扱えるサンプルコードを見ていきましょう。 扱うのは、以下の4つの場合です:
- 公開識別子もシステム識別子も指定されている → <!DOCTYPE html PUBLIC "..." "...">
- システム識別子のみが null または空 → <!DOCTYPE html PUBLIC "...">
- 公開識別子のみが null または空 → <!DOCTYPE html SYSTEM "...">
- 公開識別子もシステム識別子も null もしくは空 → IllegalArgumentException を投げる
実装は、先ほどのサンプルよりは複雑に見えますが、やっていることは同じです:
/** <!DOCTYPE html PUBLIC "..." "..."> の形の文書型宣言 */ private static final String DOCTYPE_FORMAT_PUBLIC_SYSTEM = "<!DOCTYPE %s PUBLIC \"%s\" \"%s\">"; /** <!DOCTYPE html PUBLIC "..."> の形の文書型宣言 */ private static final String DOCTYPE_FORMAT_PUBLIC = "<!DOCTYPE %s PUBLIC \"%s\">"; /** <!DOCTYPE html SYSTEM "..."> の形の文書型宣言 */ private static final String DOCTYPE_FORMAT_SYSTEM = "<!DOCTYPE %s SYSTEM \"%s\">"; /** * @param name 要素名 * @param publicId 公開識別子 * @param systemId システム識別子 * @throws IllegalArgumentException * Both public ID and system ID are null or empty. */ public static String toDtdString(String name, String publicId, String systemId){ if(!isNullOrEmpty(publicId)){ if(!isNullOrEmpty(systemId)) return String.format( DOCTYPE_FORMAT_PUBLIC_SYSTEM, name, publicId, systemId); else return String.format( DOCTYPE_FORMAT_PUBLIC, name, publicId); }else{ if(!isNullOrEmpty(systemId)) return String.format( DOCTYPE_FORMAT_SYSTEM, name, systemId); else throw new IllegalArgumentException( "At least either public ID or system ID "+ "must be non-null or non-empty."); } } private boolean isNullOrEmpty(String s){ return (s == null) || s.isEmpty(); }