JAXBでネームスペース付加・XMLスキーマ検証もできました
JAXB(Java Architecture for XML Binding)で、ネームスペースを付加したり、XMLスキーマ検証をしてみました。少し悩んだところもありましたが、問題なく動作確認できました。
ネームスペース付加
オブジェクト→XML変換
変換元データを保持するクラスは、特別なことはありません。ネームスペースを付加しない場合と同じ作りです。
変換元データを保持するクラス
@XmlRootElement(name = "person") public class PersonWithXmlns { // Getter/Setterを省略して、publicにしてあります。 public String name; public int age; }
ポイントは、package-info.javaを作成することです。上記クラスを配置してあるパッケージに、package-info.javaを作成し、次のように@XmlSchemaアノテーションで、ネームスペースを指定してあげます。
package-info.java
@XmlSchema(namespace = "http://www.example.org/person/", elementFormDefault = XmlNsForm.QUALIFIED) package jp.co.tryjava.jaxb.schema; import javax.xml.bind.annotation.XmlNsForm; import javax.xml.bind.annotation.XmlSchema;
変換処理は、ネームスペース付加しない場合と同じ処理です。下記の「期待値」に記述したように、personタグにxmlns属性が付加されるようになりました。
オブジェクト→XML変換処理
// 入力オブジェクト PersonWithXmlns person = new PersonWithXmlns(); person.name = "山田 太郎"; person.age = 20; // 出力先 StringWriter actual = new StringWriter(); // 実行 JAXB.marshal(person, actual); // 期待値 // xmlns属性が付くのがポイント! String expected = "" // + "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n" // + "<person xmlns=\"http://www.example.org/person/\">\n" // + " <name>山田 太郎</name>\n" // + " <age>20</age>\n" // + "</person>\n" // ; // 検証 assertThat(actual.toString(), is(expected));
XML→オブジェクト変換
XML→オブジェクトの変換処理は次のようになりました。xmlns属性が付加されたXMLを入力データとして渡しています。
XML→オブジェクト変換処理
// 入力XML String input = "" // + "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n" // + "<person xmlns=\"http://www.example.org/person/\">\n" // + " <name>山田 太郎</name>\n" // + " <age>20</age>\n" // + "</person>\n" // ; StringReader sr = new StringReader(input); // 実行 PersonWithXmlns actual = JAXB.unmarshal(sr, PersonWithXmlns.class); // 検証 assertThat(actual.name, is("山田 太郎")); assertThat(actual.age, is(20));
XMLスキーマ検証
オブジェクト→XML変換
※ここで「elementFormDefault="qualified"」が無いと、「org.xml.sax.SAXParseException; lineNumber: 0; columnNumber: 0; cvc-complex-type.2.4.a: 要素'name'で始まる無効なコンテンツが見つかりました。'{name}'のいずれかが必要です。」というエラーが発生してしまいました。
person.xsd
<?xml version="1.0" encoding="UTF-8"?> <schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://www.example.org/person/" targetNamespace="http://www.example.org/person/" elementFormDefault="qualified"> <element name="person" type="tns:personType"></element> <complexType name="personType"> <sequence> <element name="name" type="string"></element> <element name="age" type="int"></element> </sequence> </complexType> </schema>
オブジェクト→XMLの変換処理は、次のようになりました。JavaオブジェクトとXMLスキーマの整合性が取れていない場合は、MarshalExceptionが発生しました。
// 入力オブジェクト PersonWithXmlns person = new PersonWithXmlns(); person.name = "山田 太郎"; person.age = 20; // 出力先 StringWriter actual = new StringWriter(); // スキーマインスタンス生成 SchemaFactory schemaFactory = SchemaFactory .newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); Schema schema = schemaFactory.newSchema(getClass().getResource( "/jp/co/tryjava/jaxb/person.xsd")); // Marshallerインスタンス生成 JAXBContext context = JAXBContext.newInstance(person.getClass()); Marshaller marshaller = context.createMarshaller(); marshaller.setSchema(schema); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); // 実行 marshaller.marshal(person, actual); // 期待値 String expected = "" // + "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n" // + "<person xmlns=\"http://www.example.org/person/\">\n" // + " <name>山田 太郎</name>\n" // + " <age>20</age>\n" // + "</person>\n" // ; // 検証 assertThat(actual.toString(), is(expected));
XML→オブジェクト変換
XML→オブジェクトの変換処理は、次のようになりました。JavaオブジェクトとXMLスキーマの整合性が取れていない場合は、UnmarshalExceptionが発生しました。
// 入力XML String input = "" // + "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n" // + "<person xmlns=\"http://www.example.org/person/\">\n" // + " <name>山田 太郎</name>\n" // + " <age>20</age>\n" // + "</person>\n" // ; StringReader sr = new StringReader(input); // スキーマインスタンス生成 SchemaFactory schemaFactory = SchemaFactory .newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); Schema schema = schemaFactory.newSchema(getClass().getResource( "/jp/co/tryjava/jaxb/person.xsd")); // Unmarshallerインスタンス生成 JAXBContext context = JAXBContext .newInstance(PersonWithXmlns.class); Unmarshaller unmarshaller = context.createUnmarshaller(); unmarshaller.setSchema(schema); // 実行 PersonWithXmlns actual = (PersonWithXmlns) unmarshaller .unmarshal(sr); // 検証 assertThat(actual.name, is("山田 太郎")); assertThat(actual.age, is(20));