先日、JAXBを使用して、xmlファイルからJavaインスタンスを取得する処理を書くことがありました。この記事では、インスタンスのもとになるJavaクラスを、xsdファイル(XMLSchema)から自動生成する手順を説明します。
手順
- xsdファイル作成
- Javaクラス生成(xjcコマンド実行)
- xmlファイル作成 & xmlファイルからjavaインスタンス取得
1.xsdファイル作成
xsdファイルには、xmlの定義を記述します。JavaインスタンスにとってのJavaクラスのようなものです。以下でcars.xsdを例に、XMLSchemaについて説明します。
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.example.org/cars"
xmlns:tns="http://www.example.org/cars"
elementFormDefault="qualified">
<element name="cars">
<complexType>
<sequence>
<element ref="tns:car" minOccurs="1" maxOccurs="unbounded" />
</sequence>
</complexType>
</element>
<element name="car">
<complexType>
<sequence>
<element ref="tns:maker" minOccurs="1" maxOccurs="1" />
<element ref="tns:model" minOccurs="1" maxOccurs="1" />
</sequence>
<attribute name="number" type="string"/>
</complexType>
</element>
<element name="maker" type="string" />
<element name="model" type="string" />
</schema>
以下のcars.xmlは、上のxsdファイルに基づいて記述されたxmlファイルです。
<?xml version="1.0" encoding="UTF-8"?>
<cars xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.example.org/cars"
xsi:schemalocation="http://www.example.org/cars cars.xsd">
<car number="0001">
<maker>HONDA</maker>
<model>civic</model>
</car>
<car number="0002">
<maker>LOTUS</maker>
<model>elise</model>
</car>
</cars>
1.1.schema要素
名前空間を宣言します。
<schema xmlns="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.example.org/cars"
xmlns:tns="http://www.example.org/cars"
elementFormDefault="qualified">
<!-- 略 -->
</schema>
- xmlns属性では、XMLSchema(xmlの定義)であることを宣言しています。
- targetNameSpace属性では、このxsdファイルで記述する、xml定義の名前空間を宣言しています。
- xmlns:tns属性では、tnsというプレフィックスと、このxsdファイルで記述する、xml定義の名前空間を結びつけています。targetNameSpace属性と同じである必要があります。
1.2.element要素~その1~
xmlの要素を定義します。ここでは、cars要素を定義しています。
<!-- 略 -->
<element name="cars">
<complexType>
<sequence>
<element ref="tns:car" minOccurs="1" maxOccurs="unbounded" />
</sequence>
</complexType>
</element>
<!-- 略 -->
- name属性では、要素の名前を設定します。
- complexType要素は、定義する要素が、属性や子要素を持つ場合に設定します。
- sequence要素は、定義する要素が親要素を持つ場合に設定します。
- element要素は、要素を定義します。ここでは子要素carを定義しています。
- ref属性は、他の要素への参照を設定します。ここでは、後述 name="car"を設定したelement要素を参照しています。
- minOccur属性は、最小出現回数を設定します。1を設定すると、必須の要素となります。
- maxOccur属性は、最大出現回数を設定します。unboundedを設定すると、何度でも記述できる要素となります。またunboundedとすると、生成された当要素のJavaインスタンスは、親要素のJavaインスタンスにおいてList型で保持されます。
1.3.element要素~その2~
複数の子要素と、属性を持つ場合は以下のように記述します。ここでは、car要素を定義しています。
<!-- 略 -->
<element name="car">
<complexType>
<sequence>
<element ref="tns:maker" minOccurs="1" maxOccurs="1" />
<element ref="tns:model" minOccurs="1" maxOccurs="1" />
</sequence>
<attribute name="number" type="string"/>
</complexType>
</element>
<!-- 略 -->
- attribute要素では、属性を定義します。
- name属性では、属性名を定義します。
- type属性では、型を定義します。
1.4.element要素~その3~
属性も子要素も持たない場合は以下のように記述します。
<!-- 略 -->
<element name="maker" type="string" />
<element name="model" type="string" />
<!-- 略 -->
2.Javaクラスの生成(xjcコマンドの実行)
xjcコマンドを実行し、Javaクラスを生成します。macosのターミナルで実行しています。windowsでも同様にxjcコマンドで、Javaクラスを生成します。
$ xjc cars.xsd
以下のように、Javaクラスが生成されます。生成される場所は、xsdファイルのschema要素 targetNameSpace属性で設定したパスです。
$ xjc cars.xsd
スキーマの解析中...
スキーマのコンパイル中...
org/example/cars/Car.java
org/example/cars/Cars.java
org/example/cars/ObjectFactory.java
org/example/cars/package-info.java
3. xmlファイル作成 & xmlファイルからjavaインスタンス取得
3.1.xmlファイル作成
xmlファイルを作成します。以下のサンプルは上にも書きました。このxmlファイルから、JAXBを使用して、Javaインスタンスを取得します。
<?xml version="1.0" encoding="UTF-8"?>
<cars xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.example.org/cars"
xsi:schemalocation="http://www.example.org/cars cars.xsd">
<car number="0001">
<maker>HONDA</maker>
<model>civic</model>
</car>
<car number="0002">
<maker>LOTUS</maker>
<model>elise</model>
</car>
</cars>
- ルート要素carsのxmlns属性に、xsdファイルのtargetNameSpace属性に設定した名前空間を設定します。
- xsi:schemalocation属性には、名前空間とxsdファイルのパスをスペース区切りで記述します。
3.2.xmlファイルからJavaインスタンス取得
上のxmlファイルからCarsインスタンスを取得します。
package test;
public class Main {
public static void main(String[] args) {
CarManager manager = new CarManager();
Cars cars = manager.getCars();
for (Car car : cars.car) {
System.out.println(car.getModel());
System.out.println(" number:[" + car.getNumber() + "]");
System.out.println(" maker:[" + car.getMaker() + "]");
}
}
}
package test;
import java.io.File;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
public class CarManager {
public Cars getCars() {
File file = new File("/Users/ukiuki/Documents/workspace/JAXBTest/src/test/cars.xml");
try {
JAXBContext context = JAXBContext.newInstance(Cars.class);
Unmarshaller unmarshaller = context.createUnmarshaller();
return (Cars) unmarshaller.unmarshal(file);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
以下は、コンソールです。
civic
number:[0001]
maker:[HONDA]
elise
number:[0002]
maker:[LOTUS]
参考
参考にしました。ありがとうございます。
JAXBによるXMLデータとプログラムの双方向結合
以上です。ありがとうございました。