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アノテーションで、ネームスペースを指定してあげます。
@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属性が付加されるようになりました。
// 入力オブジェクト
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
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変換
まずは、次のようなXMLスキーマファイルを用意しました。
※ここで「elementFormDefault="qualified"」が無いと、「org.xml.sax.SAXParseException; lineNumber: 0; columnNumber: 0; cvc-complex-type.2.4.a: 要素'name'で始まる無効なコンテンツが見つかりました。'{name}'のいずれかが必要です。」というエラーが発生してしまいました。
<?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));