xmlファイルの書き方

#XMLファイルの書き方について振り返りたい！
現在の案件先（Java）で、xmlファイルを活用する機会があり、勉強したので、ちらっと書いときます。
今回は、Javaで活用できる形式です！

的外れなことを記載していたらご指摘よろしくお願いします。

##そもそもxmlファイルって？
extensible Markup Languageといい、簡単に言うと、**データをやり取りするために利用されるファイル**です。
HTMLと同じ、マークアップ言語であり、**タグ**を使って、記載していきます。
（ちなみに、Javaはコンパイラ言語、PHPなどはスクリプト言語と言います）

HTMLに直接書き込んだり、DBから出力すればよくないかと思うかもしれませんが、xmlファイルに定義することでどのようなデータを出力するか明記することで、可読性や保守性を向上することができます。
特に大規模なシステムになると情報1つ出力するだけでも、細心の注意が必要なので実装することが大切です！

簡単に言うと、こんな感じです。

```Okozukai.xml
<?xml version="1.0" encoding="Shift_JIS"?>
<買い物リスト>
  <内容>
    <日付>8月21日</日付>
    <買う物>カレー</買う物>
    <金額>500円</金額>
  </内容>
<内容>
    <日付>8月22日</日付>
    <買う物>ラーメン</買う物>
    <金額>600円</金額>
  </内容>
<内容>
    <日付>8月2３日</日付>
    <買う物>寿司</買う物>
    <金額>１5000円</金額>
  </内容>
</買い物リスト>
```
このような書き方をします！

詳しく見ていきましょう！

##タグ一覧
まずは、必要なタグ一覧から見ていきます。

###サーブレット\<servlet>
|要素　|必須　|内容　|
|:|:|:|
|\<servlet-name>|○　|web.xmlにて、サーブレットを定義するために記載する。　|
|\<display-name>|-　|GUIツールによって表示される名前。　|
|\<description> |-　|サーブレットのテキストによる説明。　|
|\<servlet-class>　|-　|サーブレットの完全修飾名のこと。<servlet-class>と<jsp-file>は必ず入れる必要はありません。オプションのような感覚です。　|
|\<jsp-file> |- |JSPファイルのフルパス。<servlet-class>と<jsp-file>は必ず入れる必要はありません。オプションのような感覚です。 |
|\<init-param> |- |サーブレットのキーと値の初期値を設定する。 |
|\<load-on-startup> |- |サーブレットがロードされる順番を設定する。値には正の整数を指定し、値が低い順から読み込まれていく。 |
###サーブレット・マッピング<servlet-mapping>
サーブレットマッピングは、サーブレット要素とURLを紐付ける役割があります。

|要素　|内容　|
|:|:|
|\<servlet-name>|web.xmlにて、サーブレットを定義するために記載する。　|
|\<url-name>|URLを解決するために用いられる。「http://host:port+WebApplicationName」 に続く部分をサーバーによって比較され、同一の場合は、サーブレットに紐づけられたサーブレットが呼び出される。|

##web.xmlを使用した際の流れ
web.xmlを使用した際の実際の流れを見ていく。URLによって呼び出されたサーブレットのディレクトリは以下の通りである。
URL: http://host:port/AutumnServletXml/Autumn

```
AutumnServletXml // コンテキストパス
 └ WEB-INF
   └ classes
     └ AutumnServlet // サーブレットパス　＋　ここにマッピングさせるURL
```
　ファイルの中身はこんな感じです。

```Autumn.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
  <servlet>
    <servlet-name>autumnservlet</servlet-name>
    <servlet-class>AutumnServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>autumnservlet</servlet-name>
    <url-pattern>/AutumnServlet</url-pattern>
  </servlet-mapping>
</web-app>
```
次は、サーブレットを継承したファイルです。

```AutumnServlet.java

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class AutumnServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
           throws ServletException, IOException {
        // レスポンスにコンテキストタイプの設定（何も出力するか見たいな）
        response.setContentType("text/html");

　　　　　　　　　　　　　　　　// レスポンスで返す内容を設定
        PrintWriter out = response.getWriter();
        out.println("<html><head></head><body>");
        out.println("<p>Autumn Application</p>");
        out.println("<p>Hello Autumn!</p>");
        out.println("</body></html>");
    }
}
```
###実行結果
クライアントからのリクエストパスはこのようになる。

```reqeuest
http://localhost:8080/AutumnServletXml/AutumnServlet
```
ブラウザには、**Autumn Application**と**Hello Autumn!**が出力されている。
###解説
先程のAutumnServlet.javaの説明をしておきます！
・HttpServletを継承して、AutumnServletを作成します。
・doGetメソッドをオーバーロードして定義します。
・Context Typeにtext/htmlを指定する。
・HTMLに出力するためのoutオブジェクトを取得する。
・最後は出力する内容を定義する。
といった内容となってます！
##パッケージになっている場合
パッケージとは、いくつものクラスをまとめたものです。
そこで、<servlet-class>を見ていただくと、クラス名の完全修飾となっています。
これは、パッケージ名も含めて定義をする必要があると言うことです。
sampleというパッケージに入っているものと仮定すると、このような形式になります。

```AutumnSample.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
  <servlet>
    <servlet-name>autumnservlet</servlet-name>
    <servlet-class>sample.AutumnServlet</servlet-class> // sampleが追加されてます。
  </servlet>
  <servlet-mapping>
    <servlet-name>autumnservlet</servlet-name>
    <url-pattern>/AutumnServlet</url-pattern>
  </servlet-mapping>
</web-app>
```
###web.xmlの定義
```
AutumnServletXml // コンテキストパス
 └ WEB-INF
   └ classes
     └ sample // パッケージ追加
       └ Autumn // サーブレットパス　＋　ここにマッピングさせるURL
```
##web.xmlの\<init-param>による初期設定
xmlの<sample>要素の<init-param>要素を渡して、初期値設定をします。

```AutumnServlet.java
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
  <servlet>
    <servlet-name>autumnservlet</servlet-name>
    <servlet-class>AutumnServlet</servlet-class>
    <init-param> // 追加開始
      <param-name>name</param-name>
      <param-value>John</param-value>
    </init-param>
    <init-param>
      <param-name>age</param-name>
      <param-value>89</param-value>
    </init-param>　// 追加終了
  </servlet>
  <servlet-mapping>
    <servlet-name>autumnservlet</servlet-name>
    <url-pattern>/AutumnServlet</url-pattern>
  </servlet-mapping>
</web-app>
```

サーブレットはこのような内容です。

```AutumnServlet.java

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class AutumnServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // 初期設定値を取得し、変数に代入
        String name = getInitParameter("name");
        String age = getInitParameter("age");

        response.setContentType("text/html");

        PrintWriter out = response.getWriter();
        out.println("<html><head></head><body>");
        out.println("<p>Simple Application</p>");
        out.println("<p>Hello Autumn!　+ " " 　+ "名前は" + name + " " + age + "歳"</p>");
        out.println("</body></html>");
    }
}
```
###実行結果
ルートパスは、変わりません。
出力内容としては、**Simple Application**、**Hello Autumn!　名前はjohn 89歳**と出力されます。
###解説
大きくは変わっていませんが、<init-param>が使用されています。
getInitParameter("name")、getInitParameter("age")でそれぞれ値をxmlファイルから呼び出しています。
##デフォルトサーブレット
指定されたサーブレットパスがなくても、デフォルトで用意しておいたHTMLを出力します。

ディレクトリは以下の通りです。

```
AutumnServletXml // コンテキストパス
 └ WEB-INF
   └ classes
     └ AutumnServlet // サーブレットパス　＋　ここにマッピングさせるURL
     └ Default // デフォルト追加
```
web.xmlファイルの内容を定義します。

```web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
  <servlet>
    <servlet-name>autumnservlet</servlet-name>
    <servlet-class>AutumnServlet</servlet-class>
  </servlet>
  <servlet>
    <servlet-name>defaultservlet</servlet-name>
    <servlet-class>DefaultServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>autumnservlet</servlet-name>
    <url-pattern>/AutumnServlet</url-pattern>
  </servlet-mapping>
  <servlet-mapping>
    <servlet-name>defaultservlet</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>
</web-app>
```
サーブレットは以下の内容です。

```DefaultServlet.java

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class DefaultServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        response.setContentType("text/html");

        PrintWriter out = response.getWriter();
        out.println("<html><head></head><body>");
        out.println("<p>Servlet not found.</p>");
        out.println("<p>Default Servlet</p>");
        out.println("</body></html>");
    }
}
```
###実行結果
以下のような存在しないパスを指定した際に、デフォルトのHTMLが返されます。

```
// 存在しないパス
http://localhost:8080/AutumnServletXml/SummerServlet
```
出力内容は、**Servlet not found.**,**Default Servlet**となる。
###解説
サーブレットの内容としては変わらないが、web.xmlのパス指定の際に"/"を定義してあげたことで、存在しないパスを指定した時でも、HTMLが表示されるようになった。
###おまけ

```web.xml
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
```
この１行が何をしているのかの解説もしておきます！
###xmlns:xsi, xmlns, xmlns:schemaLocation
これは、**名前空間**を定義してあげています。名前空間とはxmlに限った話ではなく、ざまざまな場面で使われています。

必要性としては、HTMLには複数のxmlファイルが利用されることがあるからです。万が一、どのxmlファイルにもtitleタグがあった場合、どちらを参照したら良いか困惑してしまいます。そこで、「１号室」などを指定してあげれば、読み込む側も、困惑することなく利用することができるといった内容です。

ただ、「１号室」という定義あったとしても、星のリゾートの「１号室」なのか、帝国ホテルの「１号室」なのか分からないですよね。
したがって、どのホテルの「１号室」なのかを定義してあげることで、識別できるようにしてあげます！

イメージとしては、**ルート要素（ホテルの種類）**を定義する。次に、**ルート要素にURL（何号室）**を定義するといった順番です。

まずは、ルート要素を定義してあげます。ルート要素は、**xmlns要素**で定義します。

```web.xml
xmlns="http://xmlns.jcp.org/xml/ns/javaee" 
```
次に、URLを定義してあげます。

```web.xml
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
```
最後に、schemaLocationですが、これは、ファイルの場所を指定してあげます。というのも、名前空間はあくまで識別するためのものであり、スキーマの場所を示しているわけではないからです。

```web.xml
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
```
このタグにより、どうファイル内の同じ識別します！
###id, version
idに関しては、どのアプリのIDなのか（必須ではない）、versionは、どのバージョンのサーブレットを使用しているかなどを定義します（javaでサーブレットを使用する場合で、他の場合は別のバージョンを指定する）。
###参照したサイト
https://ponsuke-tarou.hatenablog.com/entry/2021/06/07/224803
https://www.mlab.im.dendai.ac.jp/~yamada/web/xml/namespace.html
https://www.mlab.im.dendai.ac.jp/~yamada/web/xml/namespace.html