DTDのキホン

必須というわけではないでしょうが、Webアプリケーション開発者としては、 DTDくらい知っといてもバチは当たらないでしょう。 xmlがたくさん出てくるし。

ここでは、web.xmlなどを見るとき、 知っておくと便利な最低限のDTDの説明をします。

DTDはXMLのスキーマです

DTDとはXMLのスキーマ(=XML文書の構造を定義するもの)です。 スキーマには、DTDの他にXML SchemaやRelax-NGなどがあります。 DTDは他のスキーマに比べ、出来ることは少ないですが、 簡単であるのと、古くからあることで、よく使われています。 スキーマを使うとXML文書の検証(Validation)を行うことができます。 例えば、

sex属性にはmaleとfemaleのどちらかを必ず指定する。

といった文書の決まりごとを定義し、それに合わないXMLに対しては、 検証エラーを出すことができます。Javaソースに対するコンパイラみたいな ものですね。

web.xml

まず、簡単なweb.xmlの例を示します。 ここでは、1つのサーブレットに名前をつけて定義し、 URLにマッピングを行っています。
<?xml version="1.0" encoding="ISO-8859-1"?>

  <!DOCTYPE web-app PUBLIC
  "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
  "http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app>
  <servlet>
    <servlet-name>Hoge</servlet-name>
    <servlet-class>hoge.HogeServlet</servlet-class>
    <init-param>
      <param-name>key</param-name>
      <param-value>value</param-value>
    </init-param>
  </servlet>

  <servlet-mapping>
    <servlet-name>Hoge</servlet-name>
    <url-pattern>/hoge</url-pattern>
  </servlet-mapping>
</web-app>

DTDはどこにある?

web.xmlの内容を検証するDTDはどこにあるのでしょうか? web.xmlの最初の方に書いてある
  <!DOCTYPE web-app PUBLIC
  "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
  "http://java.sun.com/dtd/web-app_2_3.dtd">
というところを見てください。 このDOCTYPE...という記述は文書型宣言(Document type declaration) と呼ばれ、このxmlファイルが、どのDTDに基づいて書かれているか を示しています。

インターネットにつながっているなら、 ブラウザで、

http://java.sun.com/dtd/web-app_2_3.dtd

にアクセスするとDTDが表示されます。

この部分が、.....2_2.dtdになっている場合、 それはサーブレットAPI 2.2でweb.xmlを宣言しているということになります。 2.2で宣言されている場合、リスナーやフィルターは使えません。

要素の順番と出現回数

DTDの最初の方のweb-app要素の定義の部分を見てみましょう。 DTDファイル自体、けっこう長いので、web-app文字列で検索した方がよいかもしれません。 ここでは、web-app要素とその子要素の定義をしています。
<!ELEMENT web-app (icon?, display-name?, description?, distributable?,
context-param*, filter*, filter-mapping*, listener*, servlet*,
servlet-mapping*, session-config?, mime-mapping*, welcome-file-list?,
error-page*, taglib*, resource-env-ref*, resource-ref*, security-constraint*,
login-config?, security-role*, env-entry*, ejb-ref*,  ejb-local-ref*)>
まず、web-appの子要素(servlet、servlet-mappingなど)には、 記述する順番があります。 順番は、上に書かれている順番です。 ","で区切られた順番に、この子要素を記述する必要があります。 <servlet>要素の後に<sevlet-mapping>が書いてあるので、 web.xmlでは、必ず、<servlet>の後に<sevlet-mapping>を記述する必要があります。

これが","でなく"|"で区切られていれば、順番でなく、 どれか1つという意味になります。

表.子要素の組み合わせ
記号 説明
, 順番に出現
| リスト内のいづれか1つが出現


次に、要素の出現回数について見てみます。 要素名の後に、"*"や"?"という記号が書いてありますが、 これは、要素の出現回数を表す記号です。

表.要素の出現回数
記号 説明
? 0回もしくは1回出現
+ 1回以上出現
* 0回以上出現
なし 1回出現

icon要素は0回か1回、servlet要素は0回以上となります。
web-app要素では、"+"や""(指定なし)がないため(必須要素がないため)、 すべての要素を書かないのもアリです。

servlet要素

次はserlvet要素について見てみましょう。 上の子"要素の組み合わせ"と"要素の出現回数"が分かれば、もう意味はわかりませすね。
<!ELEMENT servlet (icon?, servlet-name, display-name?, description?,
(servlet-class|jsp-file), init-param*, load-on-startup?, run-as?, security-role-ref*)>
出現回数指定なしの servlet-name(サーブレット名)とservlet-class|jsp-file(サーブレットクラスかJSPファイル)は、必ず1回指定する必要があります。 その他の要素は任意です。

上のweb.xmlの例のservlet要素の部分が、 DTDのとおりに書かれているのが分かりますね。
  <servlet>
    <servlet-name>Hoge</servlet-name>
    <servlet-class>hoge.HogeServlet</servlet-class>
    <init-param>
      <param-name>key</param-name>
      <param-value>value</param-value>
    </init-param>
  </servlet>
servletの子要素のinit-paramについては、 今度は、DTDのinit-paramについて見ていけばいいわけです。

以上、DTDも簡単でしょ(キソだけど)。

なお、次のバージョン(servlet2.3/JSP2.0)のweb.xmlのスキーマは XMLスキーマになるようです。