PR

では,そのPersonクラスを見てみましょう。ここでも,コメントとアノテーションを省略してあります。

package generated;
 
public class Person {

    protected String name;
    protected Integer age;
 
    public String getName() {
        return name;
    }
 
    public void setName(String value) {
        this.name = value;
    }
 
    public Integer getAge() {
        return age;
    }
 
    public void setAge(Integer value) {
        this.age = value;
    }
}

作成されたPersonクラスは,nameとageの二つのフィールドを持ちます。nameの型はStringクラス,ageの型はIntegerクラスになっています。

それ以外の部分は,nameとageに対するゲッター,セッターのみです。いわゆる,Beanと呼ばれるクラスですね。

このPersonクラスを見ると,スキーマで定義された属性がフィールドに対応することがお分かりのはずです。

ちょっと腑に落ちないのがgeneratedというパッケージです。パッケージを指定するには,xjcの-pオプションを使用するか,スキーマで名前空間を指定します。

ここでは,スキーマに記述してみることにします。

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xs:schema version="1.0"
    targetNamespace="http://xml.javainthebox.net"
    xmlns:xs="http://www.w3.org/2001/XMLSchema">
 
  <xs:complexType name="person">
    <xs:attribute name="name" type="xs:string" />
    <xs:attribute name="age" type="xs:int" />
  </xs:complexType>
</xs:schema>

赤字の部分が名前空間を表しています。パッケージ名はドメインの逆順ですが,targetNamespaceはURLで指定します。

さて,これでもう一度クラス生成をしてみましょう。

C:\jaxb>xjc person.xsd
parsing a schema...
compiling a schema...
net\javainthebox\xml\ObjectFactory.java
net\javainthebox\xml\Person.java
net\javainthebox\xml\package-info.java

今度はパッケージを表すnet\javainthebox\xmlディレクトリが作成されました。また,前回は生成されたクラスが二つだけだったのに対し,今回はpackage-info.javaを加えた三つになっています。

package-info.javaは,単にパッケージ宣言がされているだけのクラスです。

では,Personクラスを見てみましょう。

package net.javainthebox.xml;
 
public class Person {

    protected String name;
    protected Integer age;
 
    public String getName() {
        return name;
    }
 
    public void setName(String value) {
        this.name = value;
    }
 
    public Integer getAge() {
        return age;
    }
 
    public void setAge(Integer value) {
        this.age = value;
    }
}

正しくパッケージ文が記述されました。

次にスキーマとJavaの型に注目してみます。

ここで使用したスキーマではname属性はtype="xs:string"で定義されていました。文字列なので,JavaのStringクラスに対応づけられています。

一方のage属性はtype="xs:int"で定義されています。整数(正確には32bitの整数)ですから,Javaのintに対応づけられるところですが,Integerクラスに対応づけられています。

このようにスキーマとJavaのクラスをバインディングするには,スキーマの型とJavaの型を対応づける必要があります。JAXBでは,表1のように型の対応を決めています。

表1 XML SchemaからJavaへの型の対応
XML Schema Type Java Data Type
xsd:string java.lang.String
xsd:integer java.math.BigInteger
xsd:int int
xsd.long long
xsd:short short
xsd:decimal java.math.BigDecimal
xsd:float float
xsd:double double
xsd:boolean boolean
xsd:byte byte
xsd:QName javax.xml.namespace.QName
xsd:dateTime javax.xml.datatype.XMLGregorianCalendar
xsd:base64Binary byte[]
xsd:hexBinary byte[]
xsd:unsignedInt long
xsd:unsignedShort int
xsd:unsignedByte short
xsd:time javax.xml.datatype.XMLGregorianCalendar
xsd:date javax.xml.datatype.XMLGregorianCalendar
xsd:g javax.xml.datatype.XMLGregorianCalendar
xsd:anySimpleType java.lang.Object
xsd:anySimpleType java.lang.String
xsd:duration javax.xml.datatype.Duration
xsd:NOTATION javax.xml.namespace.QName

では,次のようなスキーマはどのようにJavaに変換されるでしょうか。

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xs:schema version="1.0"
    targetNamespace="http://xml.javainthebox.net" 
    xmlns:tns="http://xml.javainthebox.net"
    xmlns:xs="http://www.w3.org/2001/XMLSchema">
  
  <xs:element name="person">
    <xs:complexType>
      <xs:attribute name="name" type="xs:string"/>
      <xs:attribute name="age" type="xs:int"/>
      <xs:attribute name="sex" type="tns:sex"/>
    </xs:complexType>
  </xs:element>
 
  <xs:simpleType name="sex">
    <xs:restriction base="xs:string">
      <xs:enumeration value="MALE"/>
      <xs:enumeration value="FEMALE"/>
    </xs:restriction>
  </xs:simpleType>
</xs:schema>

このスキーマはpersonタグに性別を表すsex属性を付け加えています。sex属性の定義が赤字の部分です。sex属性はMALEもしくはFEMALEのいずれかをとる文字列です。

このスキーマからJavaのクラスを生成してみましょう。

C:\jaxb>xjc person2.xsd
parsing a schema...
compiling a schema...
net\javainthebox\xml\ObjectFactory.java
net\javainthebox\xml\Person.java
net\javainthebox\xml\Sex.java
net\javainthebox\xml\package-info.java

今までとは異なり,Sex.javaファイルが生成されました。Sex.javaファイルを次に示します。

package net.javainthebox.xml;
 
public enum Sex {
 
    MALE,
    FEMALE;
 
    public String value() {
        return name();
    }
 
    public static Sex fromValue(String v) {
        return valueOf(v);
    }
}

驚いたことに,値が限定されている性別はenumで定義されました。確かにenumを使用すると,値が限定されることが一目瞭然です。

Personクラスは次のように変更されました。

package net.javainthebox.xml;
 
public class Person {
 
    protected String name;
    protected Integer age;
    protected Sex sex;
 
    public String getName() {
        return name;
    }
 
    public void setName(String value) {
        this.name = value;
    }
 
    public Integer getAge() {
        return age;
    }
 
    public void setAge(Integer value) {
        this.age = value;
    }
 
    public Sex getSex() {
        return sex;
    }
 
    public void setSex(Sex value) {
        this.sex = value;
    }

}

フィールドにsexが追加され,sexに対するゲッター,セッターも追加されました。