Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <h1>Creating Annotated JAXB Classes from Example XML Documents</h1> <p>Often, XML documents that you need to bind with JAXB do not come with an XSD for the content, but there are some great tools for automating this work, if you have an XSD. This is the process I use to fill this gap quickly and get quality binding code. Hopefully this helps answer this question and provides a general solution for this type of problem.</p> <h2>High Level Process</h2> <p>This is the process that I used to create the code for this random piece of XML:</p> <ol> <li>Get a good quality example.</li> <li>Create an XSD from the example, using a tool called <a href="http://www.thaiopensource.com/relaxng/trang.html" rel="nofollow">Trang</a>.</li> <li>Generate your binding code from the XSD.</li> </ol> <p>The entire process took me under 5 minutes, with the tools preinstalled, and produces high quality results. This is a very simple example, but the complexity of the example XML document could easily go up, without increasing the process time or lowering quality.</p> <h2>Creating a Good Quality Example</h2> <p>The example document is the most important part of this process. For more complex structures, you may need several documents to capture the information that you need, but we will stick to a single document case. We can make an example for the problem by wrapping the provided input in a <code>&lt;div/&gt;</code>, to create a file called <code>example.xml</code>:</p> <pre><code>&lt;div&gt; &lt;div&gt; &lt;span id="x1x1"&gt; bla bla &lt;/span&gt; &lt;/div&gt; &lt;span&gt; &lt;div&gt; bla bla &lt;/div&gt; &lt;/span&gt; &lt;/div&gt; </code></pre> <p>This example demonstrates that the <code>&lt;div/&gt;</code>s and <code>&lt;span/&gt;</code>s can be nested in each other and contain content.</p> <blockquote> <p>NOTE: This HTML fragment is not valid, since block level elements cannot be nested inside inline elements. An "off the shelf" schema, and code generated from it, would probably choke on this input.</p> </blockquote> <h2>Create an XSD From the Example</h2> <p>This is the voodoo step in this process. Creating the XSD by hand would introduce a lot of work and possibility for error. Without an automated process, you might as well ditch the complexity of the generator and hand code the annotations. Luckily, there is a tool called <a href="http://www.thaiopensource.com/relaxng/trang.html" rel="nofollow">Trang</a> that will fill this gap.</p> <p><a href="http://www.thaiopensource.com/relaxng/trang.html" rel="nofollow">Trang</a> can do a lot of things, but one task that it excels at is producing XSDs from XML documents. For simple structures, it can completely handle this step. For more complex input, it can get you most of the way there.</p> <p>Trang is available from <a href="http://search.maven.org/#search%7Cga%7C1%7Ctrang" rel="nofollow">Maven Central</a> at this vector:</p> <pre><code>&lt;dependency&gt; &lt;groupId&gt;com.thaiopensource&lt;/groupId&gt; &lt;artifactId&gt;trang&lt;/artifactId&gt; &lt;version&gt;20091111&lt;/version&gt; &lt;/dependency&gt; </code></pre> <p>You can download and transform the <code>example.xml</code> document with these commands:</p> <pre><code>wget http://repo1.maven.org/maven2/com/thaiopensource/trang/20091111/trang-20091111.jar java -jar trang-20091111.jar example.xml example.xsd </code></pre> <p>This produces <code>example.xsd</code>:</p> <pre><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt; &lt;xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"&gt; &lt;xs:element name="div"&gt; &lt;xs:complexType mixed="true"&gt; &lt;xs:choice minOccurs="0" maxOccurs="unbounded"&gt; &lt;xs:element ref="div"/&gt; &lt;xs:element ref="span"/&gt; &lt;/xs:choice&gt; &lt;/xs:complexType&gt; &lt;/xs:element&gt; &lt;xs:element name="span"&gt; &lt;xs:complexType mixed="true"&gt; &lt;xs:sequence&gt; &lt;xs:element minOccurs="0" maxOccurs="unbounded" ref="div"/&gt; &lt;/xs:sequence&gt; &lt;xs:attribute name="id" type="xs:NCName"/&gt; &lt;/xs:complexType&gt; &lt;/xs:element&gt; &lt;/xs:schema&gt; </code></pre> <p>For simple documents, that is usually all it takes. For more complex structures, you may have to edit this file a little, but at least you have a working XSD as a starting point.</p> <h2>Generate Your Binding Code From the XSD</h2> <p>Now that we have an XSD, we can leverage the <a href="http://docs.oracle.com/javase/6/docs/technotes/tools/share/xjc.html" rel="nofollow">XJC</a> tool and produce the binding code that we are looking for. To run XJC, pass it an XSD, the package you want to create, and a src directory. These two commands will generate the code for <code>example.xsd</code> in a package called <code>example</code>:</p> <pre><code>mkdir src xjc -d src -p example example.xsd </code></pre> <p>Now, you will have the following files in the <code>src</code> directory:</p> <pre><code>src/example/Div.java src/example/ObjectFactory.java src/example/Span.java </code></pre> <p>I have included the contents of the files at the end of this article, but here is the piece we are interested in, from <code>Span.java</code>:</p> <pre><code>@XmlElementRefs({ @XmlElementRef(name = "div", type = Div.class), @XmlElementRef(name = "span", type = Span.class) }) @XmlMixed protected List&lt;Object&gt; content; </code></pre> <p>Although hand coding the annotations can work, automating the creation of these files can save time and improve quality. It also gives you access to all of the plugins that are available for the XJC tool.</p> <hr> <h2>Complete Files Generated by XJC</h2> <p>example/Div.java:</p> <pre><code>// // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vJAXB 2.1.10 in JDK 6 // See &lt;a href="http://java.sun.com/xml/jaxb"&gt;http://java.sun.com/xml/jaxb&lt;/a&gt; // 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; /** * &lt;p&gt;Java class for anonymous complex type. * * &lt;p&gt;The following schema fragment specifies the expected content contained within this class. * * &lt;pre&gt; * &amp;lt;complexType&gt; * &amp;lt;complexContent&gt; * &amp;lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType"&gt; * &amp;lt;choice maxOccurs="unbounded" minOccurs="0"&gt; * &amp;lt;element ref="{}div"/&gt; * &amp;lt;element ref="{}span"/&gt; * &amp;lt;/choice&gt; * &amp;lt;/restriction&gt; * &amp;lt;/complexContent&gt; * &amp;lt;/complexType&gt; * &lt;/pre&gt; * * */ @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&lt;Object&gt; content; /** * Gets the value of the content property. * * &lt;p&gt; * 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 &lt;CODE&gt;set&lt;/CODE&gt; method for the content property. * * &lt;p&gt; * For example, to add a new item, do as follows: * &lt;pre&gt; * getContent().add(newItem); * &lt;/pre&gt; * * * &lt;p&gt; * Objects of the following type(s) are allowed in the list * {@link Div } * {@link String } * {@link Span } * * */ public List&lt;Object&gt; getContent() { if (content == null) { content = new ArrayList&lt;Object&gt;(); } return this.content; } } </code></pre> <p>example/Span.java</p> <pre><code>// // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vJAXB 2.1.10 in JDK 6 // See &lt;a href="http://java.sun.com/xml/jaxb"&gt;http://java.sun.com/xml/jaxb&lt;/a&gt; // 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; /** * &lt;p&gt;Java class for anonymous complex type. * * &lt;p&gt;The following schema fragment specifies the expected content contained within this class. * * &lt;pre&gt; * &amp;lt;complexType&gt; * &amp;lt;complexContent&gt; * &amp;lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType"&gt; * &amp;lt;sequence&gt; * &amp;lt;element ref="{}div" maxOccurs="unbounded" minOccurs="0"/&gt; * &amp;lt;/sequence&gt; * &amp;lt;attribute name="id" type="{http://www.w3.org/2001/XMLSchema}NCName" /&gt; * &amp;lt;/restriction&gt; * &amp;lt;/complexContent&gt; * &amp;lt;/complexType&gt; * &lt;/pre&gt; * * */ @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "", propOrder = { "content" }) @XmlRootElement(name = "span") public class Span { @XmlElementRef(name = "div", type = Div.class) @XmlMixed protected List&lt;Object&gt; content; @XmlAttribute @XmlJavaTypeAdapter(CollapsedStringAdapter.class) @XmlSchemaType(name = "NCName") protected String id; /** * Gets the value of the content property. * * &lt;p&gt; * 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 &lt;CODE&gt;set&lt;/CODE&gt; method for the content property. * * &lt;p&gt; * For example, to add a new item, do as follows: * &lt;pre&gt; * getContent().add(newItem); * &lt;/pre&gt; * * * &lt;p&gt; * Objects of the following type(s) are allowed in the list * {@link Div } * {@link String } * * */ public List&lt;Object&gt; getContent() { if (content == null) { content = new ArrayList&lt;Object&gt;(); } 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; } } </code></pre> <p>example/ObjectFactory.java</p> <pre><code>// // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vJAXB 2.1.10 in JDK 6 // See &lt;a href="http://java.sun.com/xml/jaxb"&gt;http://java.sun.com/xml/jaxb&lt;/a&gt; // 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. * &lt;p&gt;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(); } } </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload