サンプル XML ドキュメントからのアノテーション付き JAXB クラスの作成
多くの場合、JAXB でバインドする必要がある XML ドキュメントにはコンテンツの XSD が付属していませんが、XSD がある場合は、この作業を自動化する優れたツールがいくつかあります。これは、このギャップをすばやく埋めて高品質のバインディング コードを取得するために使用するプロセスです。これがこの質問への回答に役立ち、この種の問題に対する一般的な解決策を提供してくれることを願っています。
高レベルのプロセス
これは、このランダムな XML のコードを作成するために使用したプロセスです。
- 質の高い例を入手してください。
- Trangというツールを使用して、サンプルから XSD を作成します。
- XSD からバインド コードを生成します。
ツールがプリインストールされていれば、プロセス全体に 5 分もかからず、高品質の結果が得られました。これは非常に単純な例ですが、処理時間の増加や品質の低下を伴わずに、XML ドキュメントの例は簡単に複雑になる可能性があります。
良質な例を作成する
サンプル ドキュメントは、このプロセスの最も重要な部分です。より複雑な構造の場合、必要な情報を取得するために複数の文書が必要になる場合がありますが、ここでは 1 つの文書ケースに固執します。提供された入力を でラップして<div/>
、 というファイルを作成することで、問題の例を作成できexample.xml
ます。
<div>
<div>
<span id="x1x1"> bla bla </span>
</div>
<span>
<div> bla bla </div>
</span>
</div>
この例は、と を互いに入れ子にしてコンテンツを含めることができることを<div/>
示しています。<span/>
注: ブロック レベル要素はインライン要素内にネストできないため、この HTML フラグメントは有効ではありません。「既製の」スキーマとそれから生成されたコードは、おそらくこの入力で窒息するでしょう。
例から XSD を作成する
これは、このプロセスにおけるブードゥーのステップです。XSD を手動で作成すると、多くの作業が発生し、エラーが発生する可能性があります。自動化されたプロセスがなければ、ジェネレーターの複雑さを捨てて、アノテーションを手作業でコーディングすることもできます。幸いなことに、このギャップを埋めるTrangというツールがあります。
Trangは多くのことを実行できますが、Trang が得意とするタスクの 1 つは、XML 文書から XSD を作成することです。単純な構造の場合、このステップを完全に処理できます。より複雑な入力の場合は、ほとんどの方法で取得できます。
Trang はMaven Centralから次のベクターで入手できます。
<dependency>
<groupId>com.thaiopensource</groupId>
<artifactId>trang</artifactId>
<version>20091111</version>
</dependency>
example.xml
次のコマンドを使用して、ドキュメントをダウンロードして変換できます。
wget http://repo1.maven.org/maven2/com/thaiopensource/trang/20091111/trang-20091111.jar
java -jar trang-20091111.jar example.xml example.xsd
これにより、次が生成されexample.xsd
ます。
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
<xs:element name="div">
<xs:complexType mixed="true">
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element ref="div"/>
<xs:element ref="span"/>
</xs:choice>
</xs:complexType>
</xs:element>
<xs:element name="span">
<xs:complexType mixed="true">
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="unbounded" ref="div"/>
</xs:sequence>
<xs:attribute name="id" type="xs:NCName"/>
</xs:complexType>
</xs:element>
</xs:schema>
単純なドキュメントの場合、通常はこれで十分です。より複雑な構造の場合、このファイルを少し編集する必要があるかもしれませんが、少なくとも出発点として XSD が機能しています。
XSD からバインディング コードを生成する
XSD ができたので、XJCツールを活用して、探しているバインディング コードを生成できます。XJC を実行するには、XSD、作成するパッケージ、および src ディレクトリを渡します。example.xsd
これらの 2 つのコマンドは、 というパッケージでのコードを生成しますexample
。
mkdir src
xjc -d src -p example example.xsd
src
これで、ディレクトリに次のファイルが作成されます。
src/example/Div.java
src/example/ObjectFactory.java
src/example/Span.java
この記事の最後にファイルの内容を含めましたが、これが私たちが興味を持っている部分ですSpan.java
。
@XmlElementRefs({
@XmlElementRef(name = "div", type = Div.class),
@XmlElementRef(name = "span", type = Span.class)
})
@XmlMixed
protected List<Object> content;
注釈を手動でコーディングしても機能しますが、これらのファイルの作成を自動化すると、時間を節約し、品質を向上させることができます。また、XJC ツールで使用できるすべてのプラグインにアクセスできます。
XJC によって生成された完全なファイル
例/Div.java:
//
// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vJAXB 2.1.10 in JDK 6
// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a>
// Any modifications to this file will be lost upon recompilation of the source schema.
// Generated on: 2013.03.22 at 01:15:22 PM MST
//
package example;
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElementRef;
import javax.xml.bind.annotation.XmlElementRefs;
import javax.xml.bind.annotation.XmlMixed;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
/**
* <p>Java class for anonymous complex type.
*
* <p>The following schema fragment specifies the expected content contained within this class.
*
* <pre>
* <complexType>
* <complexContent>
* <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
* <choice maxOccurs="unbounded" minOccurs="0">
* <element ref="{}div"/>
* <element ref="{}span"/>
* </choice>
* </restriction>
* </complexContent>
* </complexType>
* </pre>
*
*
*/
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
"content"
})
@XmlRootElement(name = "div")
public class Div {
@XmlElementRefs({
@XmlElementRef(name = "div", type = Div.class),
@XmlElementRef(name = "span", type = Span.class)
})
@XmlMixed
protected List<Object> content;
/**
* Gets the value of the content property.
*
* <p>
* This accessor method returns a reference to the live list,
* not a snapshot. Therefore any modification you make to the
* returned list will be present inside the JAXB object.
* This is why there is not a <CODE>set</CODE> method for the content property.
*
* <p>
* For example, to add a new item, do as follows:
* <pre>
* getContent().add(newItem);
* </pre>
*
*
* <p>
* Objects of the following type(s) are allowed in the list
* {@link Div }
* {@link String }
* {@link Span }
*
*
*/
public List<Object> getContent() {
if (content == null) {
content = new ArrayList<Object>();
}
return this.content;
}
}
例/Span.java
//
// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vJAXB 2.1.10 in JDK 6
// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a>
// Any modifications to this file will be lost upon recompilation of the source schema.
// Generated on: 2013.03.22 at 01:15:22 PM MST
//
package example;
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElementRef;
import javax.xml.bind.annotation.XmlMixed;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlSchemaType;
import javax.xml.bind.annotation.XmlType;
import javax.xml.bind.annotation.adapters.CollapsedStringAdapter;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
/**
* <p>Java class for anonymous complex type.
*
* <p>The following schema fragment specifies the expected content contained within this class.
*
* <pre>
* <complexType>
* <complexContent>
* <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
* <sequence>
* <element ref="{}div" maxOccurs="unbounded" minOccurs="0"/>
* </sequence>
* <attribute name="id" type="{http://www.w3.org/2001/XMLSchema}NCName" />
* </restriction>
* </complexContent>
* </complexType>
* </pre>
*
*
*/
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
"content"
})
@XmlRootElement(name = "span")
public class Span {
@XmlElementRef(name = "div", type = Div.class)
@XmlMixed
protected List<Object> content;
@XmlAttribute
@XmlJavaTypeAdapter(CollapsedStringAdapter.class)
@XmlSchemaType(name = "NCName")
protected String id;
/**
* Gets the value of the content property.
*
* <p>
* This accessor method returns a reference to the live list,
* not a snapshot. Therefore any modification you make to the
* returned list will be present inside the JAXB object.
* This is why there is not a <CODE>set</CODE> method for the content property.
*
* <p>
* For example, to add a new item, do as follows:
* <pre>
* getContent().add(newItem);
* </pre>
*
*
* <p>
* Objects of the following type(s) are allowed in the list
* {@link Div }
* {@link String }
*
*
*/
public List<Object> getContent() {
if (content == null) {
content = new ArrayList<Object>();
}
return this.content;
}
/**
* Gets the value of the id property.
*
* @return
* possible object is
* {@link String }
*
*/
public String getId() {
return id;
}
/**
* Sets the value of the id property.
*
* @param value
* allowed object is
* {@link String }
*
*/
public void setId(String value) {
this.id = value;
}
}
例/ObjectFactory.java
//
// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vJAXB 2.1.10 in JDK 6
// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a>
// Any modifications to this file will be lost upon recompilation of the source schema.
// Generated on: 2013.03.22 at 01:15:22 PM MST
//
package example;
import javax.xml.bind.annotation.XmlRegistry;
/**
* This object contains factory methods for each
* Java content interface and Java element interface
* generated in the example package.
* <p>An ObjectFactory allows you to programatically
* construct new instances of the Java representation
* for XML content. The Java representation of XML
* content can consist of schema derived interfaces
* and classes representing the binding of schema
* type definitions, element declarations and model
* groups. Factory methods for each of these are
* provided in this class.
*
*/
@XmlRegistry
public class ObjectFactory {
/**
* Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: example
*
*/
public ObjectFactory() {
}
/**
* Create an instance of {@link Div }
*
*/
public Div createDiv() {
return new Div();
}
/**
* Create an instance of {@link Span }
*
*/
public Span createSpan() {
return new Span();
}
}