倭マン's BLOG

くだらない日々の日記書いてます。 たまにプログラミング関連の記事書いてます。 書いてます。

DOCTYPE 宣言を扱う (1):文字列の連結

XMLDOCTYPE 宣言の文字列を構築するサンプル・コードのメモ。 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();
    }