徒然なるままに

子育てとプログラミングが同居する不思議な空間

ログメッセージ定義 (XML) の読み込み

今日は Java でログメッセージ定義 (XML) を読み込む方法について考えてみます。

だいたいの場合において、ログメッセージ定義は項目が固定 (ログ ID、ログレベル、ログメッセージ+α) だと思います。そのため、今回は DOM や SAX の API は使わずに、JAXB で XML から Java オブジェクトに一括変換します。

まず、XML は以下のような形式とします。

<?xml version="1.0" encoding="UTF-8"?>
<messages>
    <message id="1">Message 1</message>
    <message id="2">Message 2</message>
    <message id="3">Message 3</message>
    <message id="4">Message 4</message>
    <message id="5">Message 5</message>
</messages>

大きく分けて、messages というルートタグと、message というメッセージ1つ1つに相当するタグがあります。これを JAXB で、XmlMessages というクラスと XmlMessage というクラスに割り当てます。

@XmlRootElement
public class XmlMessages {

    @XmlElement
    private List<XmlMessage> message;
    
    public List<XmlMessage> getMessage() {
        return this.message;
    }
}
public class XmlMessage {
    
    @XmlAttribute
    private String id;

    @XmlValue
    private String message;
    
    public String getId() {
        return this.id;
    }
    
    public String getMessage() {
        return this.message;
    }
    
    @Override
    public String toString() {
        return new StringBuilder(32)
                .append("id:").append(id)
                .append(", ")
                .append("message:").append(message)
                .append(System.lineSeparator())
                .toString();
    }
}

messages タグの中の message タグは List で定義します。

また、いくつかアノテーションをつけていますが、今回に関しては以下のルールでつけています。

  • @XmlRootElement は、XML のルート要素をあらわすクラスにつけています。
  • @XmlElement は、XML のタグに相当する変数につけています。
  • @XmlAttribute は、XML の属性に相当する変数につけています。
  • @XmlValue は、XML の値 (開始タグと終了タグで囲まれた部分) に相当する変数につけています。

JAXB による変換処理は概ね以下のようになります。

XmlMessages messages = JAXB.unmarshal(Files.newBufferedReader(xmlPath), XmlMessages.class);

xmlPath はログメッセージ定義ファイルのパスをあらわす Path クラスのインスタンスです。Path クラスのインスタンスは Paths#get メソッドで作ることが多いと思います。

JAXB#unmarshal を呼び出すことで、XML ファイルから XmlMessages クラスのインスタンスを生成しています。このインスタンスの変数 message リストには、すべての message の情報が格納されています。

固定フォーマットの XML であれば、このように非常に簡単に Java オブジェクトに変換できます。よほど巨大なファイルを解析する用途でもない限り、性能的にも問題ないかと思いますので、すぐに XML 解析ライブラリを探すのではなく、このように自作することも検討してみても良いのではないかと思います。

次回は、WatchService と組み合わせて、XML の変更を自動検知して再読込する方法について書きたいと思います。