从示例 XML 文档创建带注释的 JAXB 类
通常,您需要与 JAXB 绑定的 XML 文档不附带内容的 XSD,但是如果您有 XSD,那么有一些很好的工具可以自动完成这项工作。这是我用来快速填补这一空白并获得高质量绑定代码的过程。希望这有助于回答这个问题,并为这类问题提供一个通用的解决方案。
高级流程
这是我用来为这段随机的 XML 创建代码的过程:
- 获得一个高质量的例子。
- 使用名为Trang的工具从示例中创建一个 XSD 。
- 从 XSD 生成绑定代码。
整个过程花了我不到 5 分钟的时间,预先安装了工具,并产生了高质量的结果。这是一个非常简单的示例,但是示例 XML 文档的复杂性很容易增加,而不会增加处理时间或降低质量。
创建一个高质量的例子
示例文档是此过程中最重要的部分。对于更复杂的结构,您可能需要多个文档来捕获您需要的信息,但我们将坚持使用单个文档案例。<div/>
我们可以通过将提供的输入包装在, 中来创建一个名为 的文件来为问题举例example.xml
:
<div>
<div>
<span id="x1x1"> bla bla </span>
</div>
<span>
<div> bla bla </div>
</span>
</div>
此示例演示了<div/>
s 和<span/>
s 可以相互嵌套并包含内容。
注意:此 HTML 片段无效,因为块级元素不能嵌套在内联元素中。一个“现成的”模式,以及由此生成的代码,可能会在这个输入上窒息。
从示例创建 XSD
这是此过程中的伏都教步骤。手动创建 XSD 会带来大量工作和出错的可能性。如果没有自动化过程,您不妨放弃生成器的复杂性并手动编码注释。幸运的是,有一个名为Trang的工具可以填补这一空白。
Trang可以做很多事情,但它擅长的一项任务是从 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
在一个名为的包中生成代码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();
}
}