9
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

JAXBでネームスペース付加・XMLスキーマ検証もできました

Posted at

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変換

まずは、次のような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が発生しました。

オブジェクト→XML変換処理(XMLスキーマ検証あり)
// 入力オブジェクト
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→オブジェクト変換処理(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);

// スキーマインスタンス生成
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));

参考ページ

JAXBと名前空間と - Starlight

9
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?