Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<h1>TL;DR</h1> <p>For</p> <pre><code>@XmlElementRef(name="foo", required=false) protected JAXBElement&lt;String&gt; foo; </code></pre> <p>An absent node in the document will correspond to this field being null. An XML element present in the document with <code>xsi:nil="true"</code> will correspond to the value being an instance of <code>JAXBElement</code> with a value of <code>null</code>.</p> <p>You can also provide an XML schema instead of having JAXB generate one using the <code>location</code> property on the package level <code>@XmlSchema</code> annotation.</p> <pre><code>@XmlSchema( ... location="http://www.example.com/schema/root.xsd") package forum19665550; import javax.xml.bind.annotation.XmlSchema; </code></pre> <hr> <h1>Marshal/Unmarshal</h1> <h2>Java Model</h2> <p><strong>Root</strong></p> <p>This is an object with two fields that can represent optional and nillable data.</p> <pre><code>import javax.xml.bind.JAXBElement; import javax.xml.bind.annotation.*; @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) public class Root { @XmlElementRef(name="foo", required=false) protected JAXBElement&lt;String&gt; foo; @XmlElementRef(name="bar", required=false) protected JAXBElement&lt;String&gt; bar; } </code></pre> <p><strong>ObjectFactory</strong></p> <pre><code>import javax.xml.bind.JAXBElement; import javax.xml.bind.annotation.*; import javax.xml.namespace.QName; @XmlRegistry public class ObjectFactory { @XmlElementDecl(name="foo") public JAXBElement&lt;String&gt; createFoo(String foo) { return new JAXBElement&lt;String&gt;(new QName("foo"), String.class, foo); } @XmlElementDecl(name="bar") public JAXBElement&lt;String&gt; createBar(String bar) { return new JAXBElement&lt;String&gt;(new QName("bar"), String.class, bar); } } </code></pre> <h2>Demo Code</h2> <p><strong>Demo</strong></p> <p>The demo code below will investigate the differences in the values for <code>foo</code> and <code>bar</code>. You can use the <code>JAXBIntrospector</code> class to get the real value for an instance of <code>JAXBElement</code>. There is a bug in EclipseLink JAXB (MOXy) related to unmarshalling an instance of <code>JAXBElement</code> wrapping a null value (see: <a href="http://bugs.eclipse.org/420746" rel="noreferrer">http://bugs.eclipse.org/420746</a>).</p> <pre><code>import java.io.File; import javax.xml.bind.*; public class Demo { public static void main(String[] args) throws Exception { JAXBContext jc = JAXBContext.newInstance(Root.class, ObjectFactory.class); Unmarshaller unmarshaller = jc.createUnmarshaller(); File xml = new File("src/forum19665550/input.xml"); Root root = (Root) unmarshaller.unmarshal(xml); System.out.println("foo was set: " + (root.foo != null)); System.out.println("bar was set: " + (root.bar != null)); System.out.println("foo value: " + root.foo); System.out.println("bar value: " + root.bar); System.out.println("foo unwrapped value: " + JAXBIntrospector.getValue(root.foo)); System.out.println("bar unwrapped value: " + JAXBIntrospector.getValue(root.bar)); Marshaller marshaller = jc.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); marshaller.marshal(root, System.out); } } </code></pre> <p><strong>input.xml/Output</strong></p> <p>In the resulting output we see that we can differentiate between an element being absent from the document and an element with `xsi:nil="true" and still have the resulting value be null.</p> <pre><code>foo was set: false bar was set: true foo value: null bar value: javax.xml.bind.JAXBElement@4af42ea0 foo unwrapped value: null bar unwrapped value: null &lt;?xml version="1.0" encoding="UTF-8" standalone="yes"?&gt; &lt;root&gt; &lt;bar xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/&gt; </code></pre> <h2> </h2> <h1>Generating an XML Schema</h1> <h2>Demo Code</h2> <p><strong>GenerateSchema</strong></p> <p>Below is some JAXB code that will generate an XML Schema from the annotated model.</p> <pre><code>import java.io.IOException; import javax.xml.bind.*; import javax.xml.transform.Result; import javax.xml.transform.stream.StreamResult; public class GenerateSchema { public static void main(String[] args) throws Exception { JAXBContext jc = JAXBContext.newInstance(Root.class); jc.generateSchema(new SchemaOutputResolver() { @Override public Result createOutput(String namespaceUri, String suggestedFileName) throws IOException { StreamResult result = new StreamResult(System.out); result.setSystemId(suggestedFileName); return result; } }); } } </code></pre> <p><strong>Output</strong></p> <p>Here is the resulting XML Schema. You are correct that it doesn't indicate that the <code>foo</code> and <code>bar</code> elements are nillable.</p> <pre><code>&lt;?xml version="1.0" encoding="UTF-8" standalone="yes"?&gt; &lt;xs:schema version="1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema"&gt; &lt;xs:element name="bar" type="xs:string"/&gt; &lt;xs:element name="foo" type="xs:string"/&gt; &lt;xs:element name="root" type="root"/&gt; &lt;xs:complexType name="root"&gt; &lt;xs:sequence&gt; &lt;xs:element ref="foo" minOccurs="0"/&gt; &lt;xs:element ref="bar" minOccurs="0"/&gt; &lt;/xs:sequence&gt; &lt;/xs:complexType&gt; &lt;/xs:schema&gt; </code></pre> <hr> <h2>Providing an XML Schema</h2> <p>Instead of having JAXB derive an XML Schema from your model, you can point to your existing one that will contain more information.</p> <p><strong>package-info</strong></p> <p>This is done by specifying the <code>location</code> property on the package level <code>@XmlSchema</code> annotation.</p> <pre><code>@XmlSchema( ... location="http://www.example.com/schema/root.xsd") package forum19665550; import javax.xml.bind.annotation.XmlSchema; </code></pre>
 

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