You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@juneau.apache.org by ja...@apache.org on 2016/08/09 19:53:43 UTC
[10/51] [partial] incubator-juneau git commit: Rename project
directories.
http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/e6bf97a8/juneau-core/src/main/java/org/apache/juneau/xml/package.html
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/xml/package.html b/juneau-core/src/main/java/org/apache/juneau/xml/package.html
new file mode 100644
index 0000000..16ea21d
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/xml/package.html
@@ -0,0 +1,2158 @@
+<!DOCTYPE HTML>
+<!--
+/***************************************************************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ *
+ ***************************************************************************************************************************/
+ -->
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <style type="text/css">
+ /* For viewing in Page Designer */
+ @IMPORT url("../../../../../../javadoc.css");
+
+ /* For viewing in REST interface */
+ @IMPORT url("../htdocs/javadoc.css");
+ body {
+ margin: 20px;
+ }
+ </style>
+ <script>
+ /* Replace all @code and @link tags. */
+ window.onload = function() {
+ document.body.innerHTML = document.body.innerHTML.replace(/\{\@code ([^\}]+)\}/g, '<code>$1</code>');
+ document.body.innerHTML = document.body.innerHTML.replace(/\{\@link (([^\}]+)\.)?([^\.\}]+)\}/g, '<code>$3</code>');
+ }
+ </script>
+</head>
+<body>
+<p>XML serialization and parsing support</p>
+<script>
+ function toggle(x) {
+ var div = x.nextSibling;
+ while (div != null && div.nodeType != 1)
+ div = div.nextSibling;
+ if (div != null) {
+ var d = div.style.display;
+ if (d == 'block' || d == '') {
+ div.style.display = 'none';
+ x.className += " closed";
+ } else {
+ div.style.display = 'block';
+ x.className = x.className.replace(/(?:^|\s)closed(?!\S)/g , '' );
+ }
+ }
+ }
+</script>
+
+<a id='TOC'></a><h5 class='toc'>Table of Contents</h5>
+<ol class='toc'>
+ <li><p><a class='doclink' href='#Overview'>XML support overview</a></p>
+ <ol>
+ <li><p><a class='doclink' href='#OverviewExample'>Example</a></p>
+ </ol>
+ <li><p><a class='doclink' href='#XmlSerializer'>XmlSerializer class</a></p>
+ <ol>
+ <li><p><a class='doclink' href='#XmlAnnotation'>@Xml annotations</a></p>
+ <ol>
+ <li><p><a class='doclink' href='#XmlChildName'>@Xml.childName()</a></p>
+ <li><p><a class='doclink' href='#XmlFormat'>@Xml.format()</a></p>
+ <li><p><a class='doclink' href='#XmlContentHandler'>@Xml.contentHandler()</a></p>
+ </ol>
+ <li><p><a class='doclink' href='#Namespaces'>Namespaces</a></p>
+ <ol>
+ <li><p><a class='doclink' href='#AutoDetectNamespaces'>Auto-detection of namespaces</a></p>
+ </ol>
+ <li><p><a class='doclink' href='#UriProperties'>URI properties</a></p>
+ <li><p><a class='doclink' href='#BeanAnnotations'>@Bean and @BeanProperty annotations</a></p>
+ <li><p><a class='doclink' href='#Collections'>Collections</a></p>
+ <li><p><a class='doclink' href='#XmlSchemaSupport'>XML-Schema support</a></p>
+ <li><p><a class='doclink' href='#Recursion'> Non-tree models and recursion detection</a></p>
+ <li><p><a class='doclink' href='#SerializerConfigurableProperties'>Configurable properties</a></p>
+ <li><p><a class='doclink' href='#SerializerOtherNotes'>Other notes</a></p>
+ </ol>
+ <li><p><a class='doclink' href='#XmlParser'>XmlParser class</a></p>
+ <ol>
+ <li><p><a class='doclink' href='#GenericParsing'>Parsing into generic POJO models</a></p>
+ <ol>
+ <li><p><a class='doclink' href='#AddJsonTypeAttr'>Serializing with JSON-type attributes</a></p>
+ </ol>
+ <li><p><a class='doclink' href='#ParserConfigurableProperties'>Configurable properties</a></p>
+ <li><p><a class='doclink' href='#ParserOtherNotes'>Other notes</a></p>
+ </ol>
+ <li><p><a class='doclink' href='#RestApiSupport'>REST API support</a></p>
+ <ol>
+ <li><p><a class='doclink' href='#RestServerSupport'>REST server support</a></p>
+ <ol>
+ <li><p><a class='doclink' href='#RestServletDefault'>Using RestServletDefault</a></p>
+ <li><p><a class='doclink' href='#RestServlet'>Using RestServlet with annotations</a></p>
+ <li><p><a class='doclink' href='#DefaultProvider'>Using JAX-RS DefaultProvider</a></p>
+ <li><p><a class='doclink' href='#BaseProvider'>Using JAX-RS BaseProvider with annotations</a></p>
+ </ol>
+ <li><p><a class='doclink' href='#RestClientSupport'>REST client support</a></p>
+ </ol>
+</ol>
+
+<!-- ======================================================================================================== -->
+<a id="Overview"></a>
+<h2 class='topic' onclick='toggle(this)'>1 - XML support overview</h2>
+<div class='topic'>
+ <p>
+ Juneau supports converting arbitrary POJOs to and from XML using ultra-efficient serializers and parsers.<br>
+ The XML serializer converts POJOs directly to XML without the need for intermediate DOM objects.<br>
+ Likewise, the XML parser uses a STaX parser and creates POJOs directly without intermediate DOM objects.
+ </p>
+ <p>
+ Unlike frameworks such as JAXB, Juneau does not require POJO classes to be annotated to produce
+ and consume XML.<br>
+ For example, it can serialize and parse instances of any of the following POJO types:
+ </p>
+ <ul class='spaced-list'>
+ <li>Java primitive objects (e.g. <code>String</code>, <code>Integer</code>, <code>Boolean</code>, <code>Float</code>).
+ <li>Java collections framework objects (e.g. <code>HashSet</code>, <code>TreeMap</code>) containing anything on this list.
+ <li>Multi-dimensional arrays of any type on this list.
+ <li>Java Beans with properties of any type on this list.
+ <li>Classes with standard transformations to and from <code>Strings</code> (e.g. classes containing <code>toString()</code>, <code>fromString()</code>, <code>valueOf()</code>, <code>constructor(String)</code>).
+ </ul>
+ <p>
+ In addition to the types shown above, Juneau includes the ability to define transforms to transform non-standard object and
+ property types to serializable forms (e.g. to transform <code>Calendars</code> to and from <code>ISO8601</code> strings,
+ or <code>byte[]</code> arrays to and from base-64 encoded strings).<br>
+ These transforms can be associated with serializers/parsers, or can be associated with classes or bean properties through type and method annotations.
+ </p>
+ <p>
+ Refer to <a href='../package-summary.html#PojoCategories' class='doclink'>POJO Categories</a> for a complete definition of supported POJOs.
+ </p>
+ <p>
+ While annotations are not required to produce or consume XML, several XML annotations are provided
+ for handling namespaces and fine-tuning the format of the XML produced.
+ </p>
+ <h6 class='topic'>Prerequisites</h6>
+ <p>
+ The Juneau XML serialization and parsing support does not require any external prerequisites.
+ It only requires Java 1.6 or above.
+ </p>
+
+ <!-- ======================================================================================================== -->
+ <a id="OverviewExample"></a>
+ <h3 class='topic' onclick='toggle(this)'>1.1 - XML support overview - example</h3>
+ <div class='topic'>
+ <p>
+ The example shown here is from the Address Book resource located in the <code>org.apache.juneau.sample.war</code> application.<br>
+ The POJO model consists of a <code>List</code> of <code>Person</code> beans, with each <code>Person</code> containing
+ zero or more <code>Address</code> beans.
+ </p>
+ <p>
+ When you point a browser at <code>/sample/addressBook</code>, the POJO is rendered as HTML:
+ </p>
+ <img class='bordered' src="doc-files/Example_HTML.png">
+ <p>
+ By appending <code>?Accept=<i>mediaType</i>&plainText=true</code> to the URL, you can view the data in the various supported XML formats:
+ </p>
+
+ <h6 class='figure'>Normal XML</h6>
+ <img class='bordered' src="doc-files/Example_XML.png">
+
+ <h6 class='figure'>Simplified XML</h6>
+ <img class='bordered' src="doc-files/Example_XMLSimple.png">
+
+ <p>
+ In addition to serializing POJOs to XML, Juneau includes support for serializing the POJO metamodel to XML Schema, with
+ support for multiple namespaces.
+ </p>
+
+ <h6 class='figure'>XML Schema</h6>
+ <img class='bordered' src="doc-files/Example_XMLSchema.png">
+
+ </div>
+</div>
+
+<!-- ======================================================================================================== -->
+<a id="XmlSerializer"></a>
+<h2 class='topic' onclick='toggle(this)'>2 - XmlSerializer class</h2>
+<div class='topic'>
+ <p>
+ {@link org.apache.juneau.xml.XmlSerializer} is the class used to convert POJOs to XML.<br>
+ {@link org.apache.juneau.xml.XmlDocSerializer} is a subclass that adds an XML declaration element to the output before the POJO is serialized.
+ </p>
+ <p>
+ The XML serializer includes many configurable settings.<br>
+ Static reusable instances of XML serializers are provided with commonly-used settings:
+ </p>
+ <ul class='spaced-list'>
+ <li>{@link org.apache.juneau.xml.XmlSerializer#DEFAULT} - All default settings.
+ <li>{@link org.apache.juneau.xml.XmlSerializer#DEFAULT_SQ} - Use single quotes on attributes. Typically useful for testing since it makes string comparison simpler.
+ <li>{@link org.apache.juneau.xml.XmlSerializer#DEFAULT_SQ_READABLE} - Use single quotes on attributes and add whitespace for readability.
+ <li>{@link org.apache.juneau.xml.XmlSerializer#DEFAULT_XMLJSON} - Add JSON attribute tags on non-String values for full JSON equivalency.
+ <li>{@link org.apache.juneau.xml.XmlSerializer#DEFAULT_XMLJSON_SQ} - Same as DEFAULT_XMLJSON, but use single quotes on attributes.
+ <li>{@link org.apache.juneau.xml.XmlSerializer#DEFAULT_SIMPLE} - Don't serialize XML namespaces.
+ <li>{@link org.apache.juneau.xml.XmlSerializer#DEFAULT_SIMPLE_SQ} - Same as DEFAULT_SIMPLE, but use single quotes on attributes.
+ <li>{@link org.apache.juneau.xml.XmlSerializer#DEFAULT_SIMPLE_XMLJSON_SQ} - Same as DEFAULT_XMLJSON, but ignore XML namespaces and use single quotes on attributes.
+ </ul>
+ <p>
+ In addition, DTO beans are provided that use the XML serializer and parser for the following languages:
+ </p>
+ <ul>
+ <li>{@link org.apache.juneau.dto.atom} - ATOM beans.
+ <li>{@link org.apache.juneau.dto.cognos} - Cognos beans.
+ </ul>
+ <p>
+ Refer to the package-level Javadocs for more information about those formats.
+ </p>
+ <h6 class='topic'>Notes about examples</h6>
+ <p>
+ The examples shown in this document will use single-quote, readable settings.<br>
+ For brevity, the examples will use public fields instead of getters/setters to reduce the size of the examples.<br>
+ In the real world, you'll typically want to use standard bean getters and setters.
+ </p>
+ <p>
+ To start off simple, we'll begin with the following simplified bean and build upon it.
+ </p>
+ <p class='bcode'>
+ <jk>public class</jk> Person {
+ <jc>// Bean properties</jc>
+ <jk>public int</jk> <jf>id</jf>;
+ <jk>public</jk> String <jf>name</jf>;
+
+ <jc>// Bean constructor (needed by parser)</jc>
+ <jk>public</jk> Person() {}
+
+ <jc>// Normal constructor</jc>
+ <jk>public</jk> Person(<jk>int</jk> id, String name) {
+ <jk>this</jk>.<jf>id</jf> = id;
+ <jk>this</jk>.<jf>name</jf> = name;
+ }
+ }
+ </p>
+ <p>
+ The following code shows how to convert this to simple XML (no namespaces):
+ </p>
+ <p class='bcode'>
+ <jc>// Create a new serializer with readable output, no namespaces yet.</jc>
+ XmlSerializer s = <jk>new</jk> XmlSerializer()
+ .setProperty(SerializerContext.<jsf>SERIALIZER_useIndentation</jsf>, <jk>true</jk>)
+ .setProperty(SerializerContext.<jsf>SERIALIZER_quoteChar</jsf>, <js>'\''</js>)
+ .setProperty(XmlSerializerContext.<jsf>XML_enableNamespaces</jsf>, <jk>false</jk>);
+
+ <jc>// Create our bean.</jc>
+ Person p = <jk>new</jk> Person(1, <js>"John Smith"</js>);
+
+ <jc>// Serialize the bean to XML.</jc>
+ String xml = s.serialize(p);
+ </p>
+ <p>
+ <i>Side note:</i> Serializers can also be created by cloning existing serializers:
+ </p>
+ <p class='bcode'>
+ <jc>// Create a new serializer with readable output, no namespaces yet, but use cloning method.</jc>
+ XmlSerializer s = XmlSerializer.<jsf>DEFAULT_SQ_READABLE</jsf>.clone()
+ .setProperty(XmlSerializerContext.<jsf>XML_enableNamespaces</jsf>, <jk>false</jk>);
+ </p>
+ <p>
+ The code above produces the following output:
+ </p>
+ <p class='bcode'>
+ <xt><object></xt>
+ <xt><id></xt>1<xt></id></xt>
+ <xt><name></xt>John Smith<xt></name></xt>
+ <xt></object></xt>
+ </p>
+ <p>
+ The first thing you may notice is how the bean instance is represented by the element <xt><object></xt>.<br>
+ When objects have no name associated with them, Juneau provides a default generalized name that maps to the equivalent JSON data type.<br>
+ Some cases when objects do not have names:
+ </p>
+ <ul>
+ <li>Root element
+ <li>Object in an array, collection, or map.
+ </ul>
+ <p>
+ The generalized name reflects the JSON-equivalent data type.<br>
+ The full list of generalized element names are:
+ </p>
+ <ul>
+ <li><xt><object></xt> - A bean or <code>Map</code> element.
+ <li><xt><array></xt> - An array or <code>Collection</code> element.
+ <li><xt><string></xt> - A string value.
+ <li><xt><number></xt> - An int or float value.
+ <li><xt><boolean></xt> - A boolean value.
+ <li><xt><null/></xt> - A null value.
+ </ul>
+ <p>
+ Juneau produces JSON-equivalent XML, meaning any valid JSON document can be losslessly converted into an XML equivalent.<br>
+ In fact, all of the Juneau serializers and parsers are built upon this JSON-equivalency.
+ </p>
+
+ <!-- ======================================================================================================== -->
+ <a id="XmlAnnotation"></a>
+ <h3 class='topic' onclick='toggle(this)'>2.1 - @Xml annotations</h3>
+ <div class='topic'>
+ <p>
+ Just because Juneau allows you to serialize ordinary POJOs to XML doesn't mean you are limited to just JSON-equivalent XML.<br>
+ Several annotations are provided in the {@link org.apache.juneau.xml.annotation} package for customizing the output.
+ </p>
+
+ <!-- ======================================================================================================== -->
+ <a id="XmlName"></a>
+ <h4 class='topic' onclick='toggle(this)'>2.1.1 - @Xml.name()</h4>
+ <div class='topic'>
+ <p>
+ The {@link org.apache.juneau.xml.annotation.Xml#name()} annotation can be used to override the Juneau default name on unnamed objects.
+ </p>
+ <h6 class='figure'>Example</h6>
+ <p class='bcode'>
+ <ja>@Xml</ja>(name=<js>"person"</js>)
+ <jk>public class</jk> Person {
+ ...
+ </p>
+ <h6 class='figure'>Result</h6>
+ <p class='bcode'>
+ <xt><person></xt>
+ <xt><id></xt>1<xt></id></xt>
+ <xt><name></xt>John Smith<xt></name></xt>
+ <xt></person></xt>
+ </p>
+ </div>
+
+
+ <!-- ======================================================================================================== -->
+ <a id="XmlChildName"></a>
+ <h4 class='topic' onclick='toggle(this)'>2.1.2 - @Xml.childName()</h4>
+ <div class='topic'>
+ <p>
+ The {@link org.apache.juneau.xml.annotation.Xml#childName()} annotation can be used to specify the name of XML
+ child elements for bean properties of type collection or array.
+ </p>
+ <h6 class='figure'>Example</h6>
+ <p class='bcode'>
+ <jk>public class</jk> MyBean {
+ <ja>@Xml</ja>(childName=<js>"child"</js>}
+ <jk>public</jk> String[] <jf>children</jf> = {<js>"foo"</js>,<js>"bar"</js>};
+ }
+ </p>
+ <h6 class='figure'>Results without annotation</h6>
+ <p class='bcode'>
+ <xt><object></xt>
+ <xt><children></xt>
+ <xt><string></xt>foo<xt></string></xt>
+ <xt><string></xt>bar<xt></string></xt>
+ <xt></children></xt>
+ <xt></object></xt>
+ </p>
+ <h6 class='figure'>Results with annotation</h6>
+ <p class='bcode'>
+ <xt><object></xt>
+ <xt><children></xt>
+ <xt><child></xt>foo<xt></child></xt>
+ <xt><child></xt>bar<xt></child></xt>
+ <xt></children></xt>
+ <xt></object></xt>
+ </p>
+ </div>
+
+
+ <!-- ======================================================================================================== -->
+ <a id="XmlFormat"></a>
+ <h4 class='topic' onclick='toggle(this)'>2.1.3 - @Xml.format()</h4>
+ <div class='topic'>
+ <p>
+ The {@link org.apache.juneau.xml.annotation.Xml#format()} annotation can be used to tweak the XML format of a POJO.<br>
+ The value is set to an enum value of type {@link org.apache.juneau.xml.annotation.XmlFormat}.<br>
+ This annotation can be applied to both classes and bean properties.
+ </p>
+ <h6 class='figure'>Possible values</h6>
+ <ul class='spaced-list'>
+ <li>{@link org.apache.juneau.xml.annotation.XmlFormat#NORMAL} - Normal formatting (default).
+ <li>{@link org.apache.juneau.xml.annotation.XmlFormat#ATTR} - Render as an XML attribute when it would normally be rendered as an element.<br>
+ Can be applied to classes and properties that serialize to simple types (e.g. <code>String</code>, <code>Number</code>).
+ <li>{@link org.apache.juneau.xml.annotation.XmlFormat#ELEMENT} - Render as an XML element when it would normally be rendered as an attribute.<br>
+ Can be applied to URL and ID bean properties that would normally be rendered as attributes.
+ <li>{@link org.apache.juneau.xml.annotation.XmlFormat#COLLAPSED} - Prevents collections and arrays from being enclosed in an <xt><array></xt> (or named equivalent) element.<br>
+ Can be applied to properties of type collection or array, or to classes that subclass from <code>Collection</code>.
+ <li>{@link org.apache.juneau.xml.annotation.XmlFormat#CONTENT} - Render property value directly as content of element.<br>
+ Can be used in combination with {@link org.apache.juneau.xml.annotation.Xml#contentHandler()} to produce something other than plain text, such as embedded XML.
+ </ul>
+ <h6 class='figure'>Example</h6>
+ <p class='bcode'>
+ <jk>public class</jk> MyBean {
+
+ <jc>// Normally, bean properties would be rendered as child elements of the bean element.</jc>
+ <jc>// Override so that it's rendered as a "f1='123'" attribute on the bean element instead.</jc>
+ <ja>@Xml</ja>(format=XmlFormat.<jsf>ATTR</jsf>}
+ <jk>public int</jk> f1 = 123;
+
+ <jc>// Normally, bean URL properties would be rendered as XML attributes on the bean element.</jc>
+ <jc>// Override so that it's rendered as an <href>http://foo</href> child element instead.</jc>
+ <ja>@BeanProperty</ja>(uri=<jk>true</jk>)
+ <ja>@Xml</ja>(format=XmlFormat.<jsf>ELEMENT</jsf>}
+ <jk>public</jk> URL <jf>href</jf> = <jk>new</jk> URL(<js>"http://foo"</js>);
+
+ <jc>// Normally, collection properties would be grouped under a single <children> child element on the bean element.</jc>
+ <jc>// Override so that entries are directly children of the bean element with each entry having an element name of <child>.</jc>
+ <ja>@Xml</ja>(format=XmlFormat.<jsf>COLLAPSED</jsf>, childName=<js>"child"</js>}
+ <jk>public</jk> String[] <jf>children</jf> = <js>"foo"</js>,<js>"bar"</js>};
+ }
+ </p>
+ <h6 class='figure'>Results without annotation</h6>
+ <p class='bcode'>
+ <xt><object</xt> <xa>href</xa>=<js>'http://foo'</js><xt>></xt>
+ <xt><f1></xt>123<xt></f1></xt>
+ <xt><children></xt>
+ <xt><string></xt>foo<xt></string></xt>
+ <xt><string></xt>bar<xt></string></xt>
+ <xt></children></xt>
+ <xt></object></xt>
+ </p>
+ <h6 class='figure'>Results with annotation</h6>
+ <p class='bcode'>
+ <xt><object</xt> <xa>f1</xa>=<js>'123'</js><xt>></xt>
+ <xt><href></xt>http://foo<xt></href></xt>
+ <xt><child></xt>foo<xt></child></xt>
+ <xt><child></xt>bar<xt></child></xt>
+ <xt></object></xt>
+ </p>
+ <p>
+ The {@link org.apache.juneau.xml.annotation.XmlFormat#CONTENT} annotation can be used to serialize a bean
+ straight to text without any child elements.
+ </p>
+ <h6 class='figure'>Example</h6>
+ <p class='bcode'>
+ <ja>@Xml</ja>(name=<js>"MyBean"</js>)
+ <jk>public class</jk> MyBean {
+
+ <ja>@Xml</ja>(format=XmlFormat.<jsf>CONTENT</jsf>)
+ <jk>public</jk> String beanContents = <js>"This is my bean"</js>;
+ }
+ </p>
+ <h6 class='figure'>Results</h6>
+ <p class='bcode'>
+ <xt><MyBean></xt>
+ This is my bean
+ <xt></MyBean></xt>
+ </p>
+ <p>
+ There are some restrictions when using the <jsf>CONTENT</jsf> format:
+ </p>
+ <ul class='spaced-list'>
+ <li>A bean class can only have one property denoted with <jsf>CONTENT</jsf> format.
+ <li>A bean class cannot have any other properties that would serialize to an element (attributes are okay).
+ </ul>
+ <p>
+ The class type on the property can be anything that serializes to a simple value, like a <code>String</code> or <code>Number</code>.<br>
+ Note that transforms can usually be used to convert more complex class types to simple types.
+ </p>
+ </div>
+
+
+ <!-- ======================================================================================================== -->
+ <a id="XmlContentHandler"></a>
+ <h4 class='topic' onclick='toggle(this)'>2.1.4 - @Xml.contentHandler()</h4>
+ <div class='topic'>
+ <p>
+ The {@link org.apache.juneau.xml.annotation.Xml#contentHandler()} annotation is an advanced feature that allows you to
+ define your own code for serializing and parsing the contents of a serialized bean.
+ </p>
+ <p>
+ For example, the ATOM specification allows for the media type of <code>Text</code> elements to be specified via a <xa>type</xa> attribute:
+ </p>
+ <p class='bcode'>
+ <xt><feed></xt>
+ <xt><entry></xt>
+ <xt><title</xt> <xa>type</xa>=<xs>'text'</xs>></xt>
+ A &lt;em&gt;lot&lt;/em&gt; of effort went into making this effortless
+ <xt></title></xt>
+ <xt><content</xt> <xa>type</xa>=<xs>'xhtml'</xs>></xt>
+ <xt><div</xt> <xa>xmlns</xa>=<xs>"http://www.w3.org/1999/xhtml"</xs><xt>></xt><xt><p></xt><xt><i></xt>This is the contents of this entry.<xt></i></xt><xt></p></xt><xt></div></xt>
+ <xt></content></xt>
+ <xt></entry></xt>
+ <xt></feed></xt>
+ </p>
+ <p>
+ To accomplish this, the {@link org.apache.juneau.dto.atom.Text} class uses a content handler that serializes and parses the value by inspecting the <xa>type</xa> value and then handling the content accordingly:
+ </p>
+ <p class='bcode'>
+ <jk>public class</jk> Text <jk>extends</jk> Common {
+
+ <jk>private</jk> String <jf>type</jf>;
+ <jk>private</jk> String <jf>text</jf>;
+
+ <ja>@Xml</ja>(format=<jsf>ATTR</jsf>)
+ <jk>public</jk> String getType() {
+ <jk>return</jk> <jf>type</jf>;
+ }
+
+ <jk>public</jk> Text setType(String type) {
+ <jk>this</jk>.<jf>type</jf> = type;
+ <jk>return this</jk>;
+ }
+
+ <ja>@Xml</ja>(format=<jsf>CONTENT</jsf>, contentHandler=TextContentHandler.<jk>class</jk>)
+ <jk>public</jk> String getText() {
+ <jk>return</jk> text;
+ }
+
+ <jk>public</jk> Text setText(String text) {
+ <jk>this</jk>.<jf>text</jf> = text;
+ <jk>return this</jk>;
+ }
+
+ <jc>// Converts the text to and from the appropriate media type.</jc>
+ <jk>public class</jk> TextContentHandler <jk>implements</jk> XmlContentHandler<Text> {
+
+ <ja>@Override</ja>
+ <jk>public void</jk> parse(XMLStreamReader r, Text text) <jk>throws</jk> Exception {
+ String type = text.<jf>type</jf>;
+ <jk>if</jk> (type != <jk>null</jk> && type.equals(<js>"xhtml"</js>))
+ text.<jf>text</jf> = <jsm>decode</jsm>(readXmlContents(r).trim());
+ <jk>else</jk>
+ text.<jf>text</jf> = <jsm>decode</jsm>(r.getElementText().trim());
+ }
+
+ <ja>@Override</ja>
+ <jk>public void</jk> serialize(XmlSerializerWriter w, Text text) <jk>throws</jk> Exception {
+ String type = text.<jf>type</jf>;
+ String content = text.<jf>text</jf>;
+ <jk>if</jk> (type != <jk>null</jk> && type.equals(<js>"xhtml"</js>))
+ w.encodeTextInvalidChars(content);
+ <jk>else</jk>
+ w.encodeText(content);
+ }
+ }
+ }
+ </p>
+ <p>
+ Refer to {@link org.apache.juneau.xml.XmlContentHandler} for more information.
+ </p>
+ </div>
+ </div>
+
+
+ <!-- ======================================================================================================== -->
+ <a id="Namespaces"></a>
+ <h3 class='topic' onclick='toggle(this)'>2.2 - Namespaces</h3>
+ <div class='topic'>
+ <p>
+ Let's go back to the example of our original <code>Person</code> bean class:
+ </p>
+ <p class='bcode'>
+ <jk>public class</jk> Person {
+ <jc>// Bean properties</jc>
+ <jk>public int</jk> <jf>id</jf>;
+ <jk>public</jk> String <jf>name</jf>;
+
+ <jc>// Bean constructor (needed by parser)</jc>
+ <jk>public</jk> Person() {}
+
+ <jc>// Normal constructor</jc>
+ <jk>public</jk> Person(<jk>int</jk> id, String name) {
+ <jk>this</jk>.<jf>id</jf> = id;
+ <jk>this</jk>.<jf>name</jf> = name;
+ }
+ }
+ </p>
+ <p>
+ However, this time we'll leave namespaces enabled on the serializer:
+ </p>
+ <p class='bcode'>
+ <jc>// Create a new serializer with readable output, this time with namespaces enabled.</jc>
+ XmlSerializer s = <jk>new</jk> XmlSerializer()
+ .setProperty(SerializerContext.<jsf>SERIALIZER_useIndentation</jsf>, <jk>true</jk>)
+ .setProperty(SerializerContext.<jsf>SERIALIZER_quoteChar</jsf>, <js>'\''</js>);
+
+ <jc>// Create our bean.</jc>
+ Person p = <jk>new</jk> Person(1, <js>"John Smith"</js>);
+
+ <jc>// Serialize the bean to XML.</jc>
+ String xml = s.serialize(p);
+ </p>
+ <p>
+ Now when we run this code, we'll see namespaces added to our output:
+ </p>
+ <p class='bcode'>
+ <xt><object</xt>
+ <xa>xmlns</xa>=<xs>'http://www.ibm.com/2013/Juneau'</xs>
+ <xa>xmlns:xsi</xa>=<xs>'http://www.w3.org/2001/XMLSchema-instance'</xs><xt>></xt>
+ <xt><id></xt>1<xt></id></xt>
+ <xt><name></xt>John Smith<xt></name></xt>
+ <xt></object></xt>
+ </p>
+ <p>
+ This isn't too exciting yet since we haven't specified any namespaces yet.<br>
+ Therefore, everything is defined under the default <code>Juneau</code> namespace.<br>
+ The <code>xsi</code> namespace is always present and is used to mark null property values with <code><xa>nil</xa>=<xs>'true'</xs></code>.
+ </p>
+ <p>
+ Namespaces can be defined at the following levels:
+ </p>
+ <ul class='spaced-list'>
+ <li>At the package level by using the {@link org.apache.juneau.xml.annotation.XmlSchema @XmlSchema} annotation.
+ <li>At the class level by using the {@link org.apache.juneau.xml.annotation.Xml @Xml} annotation.
+ <li>At the bean property level by using the {@link org.apache.juneau.xml.annotation.Xml @Xml} annotation.
+ </ul>
+ <p>
+ It's typically best to specify the namespaces used at the package level.<br>
+ We'll do that here for the package containing our test code.
+ </p>
+ <p class='bcode'>
+ <jc>// XML namespaces used in this package</jc>
+ <ja>@XmlSchema</ja>(
+ prefix=<js>"ab"</js>,
+ xmlNs={
+ <ja>@XmlNs</ja>(prefix=<js>"ab"</js>, namespaceURI=<js>"http://www.ibm.com/addressBook/"</js>),
+ <ja>@XmlNs</ja>(prefix=<js>"per"</js>, namespaceURI=<js>"http://www.ibm.com/person/"</js>),
+ <ja>@XmlNs</ja>(prefix=<js>"addr"</js>, namespaceURI=<js>"http://www.ibm.com/address/"</js>),
+ <ja>@XmlNs</ja>(prefix=<js>"mail"</js>, namespaceURI=<js>"http://www.ibm.com/mail/"</js>)
+ }
+ )
+ <jk>package</jk> com.ibm.sample.addressbook;
+ <jk>import</jk> org.apache.juneau.xml.annotation.*;
+ </p>
+ <p>
+ We're defining four namespaces in this package and designating <js>"http://www.ibm.com/addressBook/"</js> as the default
+ namespace for all classes and properties within this package.
+ </p>
+ <p>
+ Take special note that the <ja>@XmlSchema</ja> is modelled after the equivalent JAXB annotation, but is
+ defined in the {@link org.apache.juneau.xml.annotation} package.<br>
+ Other XML annotations are also modelled after JAXB.
+ However, since many of the features of JAXB are already implemented for all serializers and parsers
+ at a higher level through various general annotations such as {@link org.apache.juneau.annotation.Bean} and {@link org.apache.juneau.annotation.BeanProperty}
+ it was decided to maintain separate Juneau XML annotations instead of reusing JAXB annotations.<br>
+ This may change in some future implementation, but for now it was decided that having separate Juneau XML annotations was less confusing.
+ </p>
+ <p>
+ On our bean class, we'll specify to use the <js>"http://www.ibm.com/person/"</js> namespace:
+ </p>
+ <p class='bcode'>
+ <ja>@Xml</ja>(name=<js>"person"</js>, prefix=<js>"per"</js>)
+ <jk>public class</jk> Person {
+ ...
+ </p>
+ <p>
+ Now when we serialize the bean, we get the following:
+ </p>
+ <p class='bcode'>
+ <xt><per:person</xt>
+ <xa>xmlns</xa>=<xs>'http://www.ibm.com/2013/Juneau'</xs>
+ <xa>xmlns:per</xa>=<xs>'http://www.ibm.com/person/'</xs>
+ <xa>xmlns:xsi</xa>=<xs>'http://www.w3.org/2001/XMLSchema-instance'</xs><xt>></xt>
+ <xt><per:id></xt>1<xt></per:id></xt>
+ <xt><per:name></xt>John Smith<xt></per:name></xt>
+ <xt></per:person></xt>
+ </p>
+ <p>
+ We can simplify the output by setting the default namespace on the serializer so that
+ all the elements do not need to be prefixed:
+ <p class='bcode'>
+ <jc>// Create a new serializer with readable output, this time with namespaces enabled.</jc>
+ XmlSerializer s = <jk>new</jk> XmlSerializer()
+ .setProperty(SerializerContext.<jsf>SERIALIZER_useIndentation</jsf>, <jk>true</jk>)
+ .setProperty(SerializerContext.<jsf>SERIALIZER_quoteChar</jsf>, <js>'\''</js>)
+ .setProperty(XmlSerializerContext.<jsf>XML_defaultNamespaceUri</jsf>, <js>"http://www.ibm.com/person/"</js>);
+ </p>
+ <p>
+ This produces the following equivalent where the elements don't need prefixes since they're already in the default document namespace:
+ </p>
+ <p class='bcode'>
+ <xt><person</xt>
+ <xa>xmlns</xa>=<xs>'http://www.ibm.com/person/'</xs>
+ <xa>xmlns:juneau</xa>=<xs>'http://www.ibm.com/2013/Juneau'</xs>
+ <xa>xmlns:xsi</xa>=<xs>'http://www.w3.org/2001/XMLSchema-instance'</xs><xt>></xt>
+ <xt><id></xt>1<xt></id></xt>
+ <xt><name></xt>John Smith<xt></name></xt>
+ <xt></person></xt>
+ </p>
+
+
+ <!-- ======================================================================================================== -->
+ <a id="AutoDetectNamespaces"></a>
+ <h4 class='topic' onclick='toggle(this)'>2.2.1 - Auto-detection of namespaces</h4>
+ <div class='topic'>
+ <p>
+ One important property on the XML serializer class is {@link org.apache.juneau.xml.XmlSerializerContext#XML_autoDetectNamespaces XML_autoDetectNamespaces}.<br>
+ This property tells the serializer to make a first-pass over the data structure to look for namespaces defined on classes and bean properties.<br>
+ In high-performance environments, you may want to consider disabling auto-detection and providing your own explicit list of namespaces to the serializer
+ to avoid this scanning step.
+ </p>
+ <p>
+ The following code will produce the same output as before, but will perform slightly better since it avoids this prescan step.
+ </p>
+ <p class='bcode'>
+ <jc>// Create a new serializer with readable output, this time with namespaces enabled.</jc>
+ XmlSerializer s = <jk>new</jk> XmlSerializer()
+ .setProperty(SerializerContext.<jsf>SERIALIZER_useIndentation</jsf>, <jk>true</jk>)
+ .setProperty(SerializerContext.<jsf>SERIALIZER_quoteChar</jsf>, <js>'\''</js>)
+ .setProperty(XmlSerializerContext.<jsf>XML_autoDetectNamespaces</jsf>, <jk>false</jk>)
+ .setProperty(XmlSerializerContext.<jsf>XML_namespaces</jsf>, <js>"{per:'http://www.ibm.com/person/'}"</js>);
+ </p>
+ </div>
+
+ </div>
+
+ <!-- ======================================================================================================== -->
+ <a id="UriProperties"></a>
+ <h3 class='topic' onclick='toggle(this)'>2.3 - URI properties</h3>
+ <div class='topic'>
+ <p>
+ The {@link org.apache.juneau.annotation.BeanProperty#beanUri} annotation is used to identify the URI
+ of a bean.<br>
+ Typically, this property will have a class type of {@link java.net.URI} or {@link java.net.URL}, although
+ it can essentially be any type that resolves to a simple serializable type.
+ </p>
+ <p>
+ In the following code, we're adding 2 new properties.<br>
+ The first property is annotated with <ja>@BeanProperty</ja> to identify that this property is the
+ resource identifier for this bean.<br>
+ The second unannotated property is interpreted as a normal property.
+ </p>
+ <p class='bcode'>
+ <ja>@Xml</ja>(name=<js>"person"</js>, prefix=<js>"per"</js>)
+ <jk>public class</jk> Person {
+
+ <jc>// Bean properties</jc>
+ <ja>@BeanProperty</ja>(beanUri=<jk>true</jk>)
+ <jk>public</jk> URI <jf>uri</jf>;
+
+ <jk>public</jk> URI <jf>addressBookUri</jf>;
+
+ ...
+
+ <jc>// Normal constructor</jc>
+ <jk>public</jk> Person(<jk>int</jk> id, String name, String uri, String addressBookUri) <jk>throws</jk> URISyntaxException {
+ <jk>this</jk>.<jf>id</jf> = id;
+ <jk>this</jk>.<jf>name</jf> = name;
+ <jk>this</jk>.<jf>uri</jf> = <jk>new</jk> URI(uri);
+ <jk>this</jk>.<jf>addressBookUri</jf> = <jk>new</jk> URI(addressBookUri);
+ }
+ }
+ </p>
+ <p>
+ We alter our code to pass in values for these new properties.
+ </p>
+ <p class='bcode'>
+ <jc>// Create our bean.</jc>
+ Person p = <jk>new</jk> Person(1, <js>"John Smith"</js>, <js>"http://sample/addressBook/person/1"</js>, <js>"http://sample/addressBook"</js>);
+ </p>
+ <p>
+ Now when we run the sample code, we get the following:
+ </p>
+ <p class='bcode'>
+ <xt><per:person</xt>
+ <xa>xmlns</xa>=<xs>'http://www.ibm.com/2013/Juneau'</xs>
+ <xa>xmlns:per</xa>=<xs>'http://www.ibm.com/person/'</xs>
+ <xa>xmlns:xsi</xa>=<xs>'http://www.w3.org/2001/XMLSchema-instance'</xs>
+ <xa>uri</xa>=<xs>'http://sample/addressBook/person/1'</xs><xt>></xt>
+ <xt><per:id></xt>1<xt></per:id></xt>
+ <xt><per:name></xt>John Smith<xt></per:name></xt>
+ <xt><per:addressBookUri></xt>http://sample/addressBook<xt></per:addressBookUri></xt>
+ <xt></per:person></xt>
+ </p>
+ <p>
+ Notice how the bean URI property is serialized as an XML attribute while the normal URI property is
+ serialized normally as an element.
+ </p>
+ <p>
+ Bean properties that resolve as XML attributes can also be assigned namespaces.<br>
+ For example, let's assign our bean URI to another namespace.
+ </p>
+ <p class='bcode'>
+ <ja>@BeanProperty</ja>(beanUri=<jk>true</jk>)
+ <ja>@Xml</ja>(prefix=<js>"ab"</js>)
+ <jk>public</jk> URI <jf>uri</jf>;
+ </p>
+ <p>
+ Now when we run the sample code, we see that our <xa>uri</xa> attribute is assigned that namespace prefix.
+ </p>
+ <p class='bcode'>
+ <xt><per:person</xt>
+ <xa>xmlns</xa>=<xs>'http://www.ibm.com/2013/Juneau'</xs>
+ <xa>xmlns:per</xa>=<xs>'http://www.ibm.com/person/'</xs>
+ <xa>xmlns:ab</xa>=<xs>'http://www.ibm.com/addressBook/'</xs>
+ <xa>xmlns:xsi</xa>=<xs>'http://www.w3.org/2001/XMLSchema-instance'</xs>
+ <xa>ab:uri</xa>=<xs>'http://sample/addressBook/person/1'</xs><xt>></xt>
+ <xt><per:id></xt>1<xt></per:id></xt>
+ <xt><per:name></xt>John Smith<xt></per:name></xt>
+ <xt><per:addressBookUri></xt>http://sample/addressBook<xt></per:addressBookUri></xt>
+ <xt></per:person></xt>
+ </p>
+ <p>
+ The {@link org.apache.juneau.annotation.URI} annotation can also be used on classes and properties
+ to identify them as URLs when they're not instances of <code>java.net.URI</code> or <code>java.net.URL</code>
+ (not needed if <code><ja>@BeanProperty</ja>(beanUri=<jk>true</jk>)</code> is already specified).
+ </p>
+ <p>
+ The following properties would have produced the same output as before.
+ </p>
+ <p class='bcode'>
+ <jk>public class</jk> Person {
+
+ <jc>// Bean properties</jc>
+ <ja>@BeanProperty</ja>(beanUri=<jk>true</jk>) <jk>public</jk> String <jf>uri</jf>;
+ </p>
+ <p>
+ Also take note of the {@link org.apache.juneau.serializer.SerializerContext#SERIALIZER_absolutePathUriBase SERIALIZER_absolutePathUriBase} and
+ {@link org.apache.juneau.serializer.SerializerContext#SERIALIZER_relativeUriBase SERIALIZER_relativeUriBase}
+ settings that can be specified on the serializer to resolve relative and context-root-relative URIs to fully-qualfied URIs.
+ </p>
+ <p>
+ This can be useful if you want to keep the URI authority and context root information out of the bean logic layer.
+ </p>
+ <p>
+ The following code produces the same output as before, but the URIs on the beans are relative.
+ </p>
+ <p class='bcode'>
+ <jc>// Create a new serializer with readable output.</jc>
+ XmlSerializer s = <jk>new</jk> XmlSerializer()
+ .setProperty(SerializerContext.<jsf>SERIALIZER_useIndentation</jsf>, <jk>true</jk>)
+ .setProperty(SerializerContext.<jsf>SERIALIZER_quoteChar</jsf>, <js>'\''</js>)
+ .setProperty(SerializerContext.<jsf>SERIALIZER_relativeUriBase</jsf>, <js>"http://myhost/sample"</js>);
+ .setProperty(SerializerContext.<jsf>SERIALIZER_absolutePathUriBase</jsf>, <js>"http://myhost"</js>);
+
+ <jc>// Create our bean.</jc>
+ Person p = <jk>new</jk> Person(1, <js>"John Smith"</js>, <js>"person/1"</js>, <js>"/"</js>);
+
+ <jc>// Serialize the bean to RDF/XML.</jc>
+ String rdfXml = s.serialize(p);
+ </p>
+ </div>
+
+ <!-- ======================================================================================================== -->
+ <a id="BeanAnnotations"></a>
+ <h3 class='topic' onclick='toggle(this)'>2.4 - @Bean and @BeanProperty annotations</h3>
+ <div class='topic'>
+ <p>
+ The {@link org.apache.juneau.annotation.Bean @Bean} and {@link org.apache.juneau.annotation.BeanProperty @BeanProperty} annotations
+ are used to customize the behavior of beans across the entire framework.<br>
+ In addition to using them to identify the resource URI for the bean shown above, they have various other uses:
+ </p>
+ <ul class='spaced-list'>
+ <li>Hiding bean properties.
+ <li>Specifying the ordering of bean properties.
+ <li>Overriding the names of bean properties.
+ <li>Associating transforms at both the class and property level (to convert non-serializable POJOs to serializable forms).
+ </ul>
+ <p>
+ For example, we now add a <code>birthDate</code> property, and associate a transform with it to transform
+ it to an ISO8601 date-time string in GMT time.<br>
+ By default, <code>Calendars</code> are treated as beans by the framework, which is usually not how you want them serialized.<br>
+ Using transforms, we can convert them to standardized string forms.
+ </p>
+ <p class='bcode'>
+ <ja>@Xml</ja>(name=<js>"person"</js>, prefix=<js>"per"</js>)
+ <jk>public class</jk> Person {
+
+ <jc>// Bean properties</jc>
+ <ja>@BeanProperty</ja>(transform=CalendarTransform.ISO8601DTZ.<jk>class</jk>) <jk>public</jk> Calendar birthDate;
+ ...
+
+ <jc>// Normal constructor</jc>
+ <jk>public</jk> Person(<jk>int</jk> id, String name, String uri, String addressBookUri, String birthDate) <jk>throws</jk> Exception {
+ ...
+ <jk>this</jk>.<jf>birthDate</jf> = <jk>new</jk> GregorianCalendar();
+ <jk>this</jk>.<jf>birthDate</jf>.setTime(DateFormat.<jsm>getDateInstance</jsm>(DateFormat.<jsf>MEDIUM</jsf>).parse(birthDate));
+ }
+ }
+ </p>
+ <p>
+ Next, we alter our code to pass in the birthdate:
+ </p>
+ <p class='bcode'>
+ <jc>// Create our bean.</jc>
+ Person p = <jk>new</jk> Person(1, <js>"John Smith"</js>, <js>"http://sample/addressBook/person/1"</js>, <js>"http://sample/addressBook"</js>, <js>"Aug 12, 1946"</js>);
+ </p>
+ <p>
+ Now when we rerun the sample code, we'll get the following:
+ </p>
+ <p class='bcode'>
+ <xt><per:person</xt>
+ <xa>xmlns</xa>=<xs>'http://www.ibm.com/2013/Juneau'</xs>
+ <xa>xmlns:per</xa>=<xs>'http://www.ibm.com/person/'</xs>
+ <xa>xmlns:xsi</xa>=<xs>'http://www.w3.org/2001/XMLSchema-instance'</xs>
+ <xa>uri</xa>=<xs>'http://sample/addressBook/person/1'</xs><xt>></xt>
+ <xt><per:id></xt>1<xt></per:id></xt>
+ <xt><per:name></xt>John Smith<xt></per:name></xt>
+ <xt><per:addressBookUri></xt>http://sample/addressBook<xt></per:addressBookUri></xt>
+ <xt><per:birthDate></xt>1946-08-12T00:00:00Z<xt></per:birthDate></xt>
+ <xt></per:person></xt>
+ </p>
+ <p>
+ Another useful feature is the {@link org.apache.juneau.annotation.Bean#propertyNamer()} annotation that allows you to plug in your own
+ logic for determining bean property names.<br>
+ The {@link org.apache.juneau.PropertyNamerDashedLC} is an example of an alternate property namer.
+ It converts bean property names to lowercase-dashed format.
+ </p>
+ <h6 class='figure'>Example</h6>
+ <p class='bcode'>
+ <ja>@Xml</ja>(name=<js>"person"</js>, prefix=<js>"per"</js>)
+ <ja>@Bean</ja>(propertyNamer=PropertyNamerDashedLC.<jk>class</jk>)
+ <jk>public class</jk> Person {
+ ...
+ </p>
+ <h6 class='figure'>Results</h6>
+ <p class='bcode'>
+ <xt><per:person</xt>
+ <xa>xmlns</xa>=<xs>'http://www.ibm.com/2013/Juneau'</xs>
+ <xa>xmlns:per</xa>=<xs>'http://www.ibm.com/person/'</xs>
+ <xa>xmlns:xsi</xa>=<xs>'http://www.w3.org/2001/XMLSchema-instance'</xs>
+ <xa>uri</xa>=<xs>'http://sample/addressBook/person/1'</xs><xt>></xt>
+ <xt><per:id></xt>1<xt></per:id></xt>
+ <xt><per:name></xt>John Smith<xt></per:name></xt>
+ <xt><per:address-book-uri></xt>http://sample/addressBook<xt></per:address-book-uri></xt>
+ <xt><per:birth-date></xt>1946-08-12T04:00:00Z<xt></per:birth-date></xt>
+ <xt></per:person></xt>
+ </p>
+ </div>
+
+
+ <!-- ======================================================================================================== -->
+ <a id="Collections"></a>
+ <h3 class='topic' onclick='toggle(this)'>2.5 - Collections</h3>
+ <div class='topic'>
+ <p>
+ In our example, let's add a list-of-beans property to our sample class:
+ </p>
+ <p class='bcode'>
+ <jk>public class</jk> Person {
+
+ <jc>// Bean properties</jc>
+ <jk>public</jk> LinkedList<Address> <jf>addresses</jf> = <jk>new</jk> LinkedList<Address>();
+ ...
+ }
+ </p>
+ <p>
+ The <code>Address</code> class has the following properties defined:
+ </p>
+ <p class='bcode'>
+ <ja>@Xml</ja>(name=<js>"address"</js>, prefix=<js>"addr"</js>)
+ <jk>public class</jk> Address {
+
+ <jc>// Bean properties</jc>
+ <ja>@BeanProperty</ja>(beanUri=<jk>true</jk>) <jk>public</jk> URI <jf>uri</jf>;
+ <jk>public</jk> URI <jf>personUri</jf>;
+ <jk>public int</jk> <jf>id</jf>;
+ <ja>@Xml</ja>(prefix=<js>"mail"</js>) <jk>public</jk> String <jf>street</jf>, <jf>city</jf>, <jf>state</jf>;
+ <ja>@Xml</ja>(prefix=<js>"mail"</js>) <jk>public int</jk> <jf>zip</jf>;
+ <jk>public boolean</jk> <jf>isCurrent</jf>;
+ }
+ </p>
+ <p>
+ Next, add some quick-and-dirty code to add an address to our person bean:
+ </p>
+ <p class='bcode'>
+ <jc>// Create a new serializer with readable output.</jc>
+ XmlSerializer s = <jk>new</jk> XmlSerializer()
+ .setProperty(SerializerContext.<jsf>SERIALIZER_useIndentation</jsf>, <jk>true</jk>)
+ .setProperty(SerializerContext.<jsf>SERIALIZER_quoteChar</jsf>, <js>'\''</js>);
+
+ <jc>// Create our bean.</jc>
+ Person p = <jk>new</jk> Person(1, <js>"John Smith"</js>, <js>"http://sample/addressBook/person/1"</js>, <js>"http://sample/addressBook"</js>, <js>"Aug 12, 1946"</js>);
+ Address a = <jk>new</jk> Address();
+ a.<jf>uri</jf> = <jk>new</jk> URI(<js>"http://sample/addressBook/address/1"</js>);
+ a.<jf>personUri</jf> = <jk>new</jk> URI(<js>"http://sample/addressBook/person/1"</js>);
+ a.<jf>id</jf> = 1;
+ a.<jf>street</jf> = <js>"100 Main Street"</js>;
+ a.<jf>city</jf> = <js>"Anywhereville"</js>;
+ a.<jf>state</jf> = <js>"NY"</js>;
+ a.<jf>zip</jf> = 12345;
+ a.<jf>isCurrent</jf> = <jk>true</jk>;
+ p.<jf>addresses</jf>.add(a);
+ </p>
+ <p>
+ Now when we run the sample code, we get the following:
+ </p>
+ <p class='bcode'>
+ <xt><per:person</xt>
+ <xa>xmlns</xa>=<xs>'http://www.ibm.com/2013/Juneau'</xs>
+ <xa>xmlns:per</xa>=<xs>'http://www.ibm.com/person/'</xs>
+ <xa>xmlns:addr</xa>=<xs>'http://www.ibm.com/address/'</xs>
+ <xa>xmlns:mail</xa>=<xs>'http://www.ibm.com/mail/'</xs>
+ <xa>xmlns:xsi</xa>=<xs>'http://www.w3.org/2001/XMLSchema-instance'</xs>
+ <xa>uri</xa>=<xs>'http://sample/addressBook/person/1'</xs><xt>></xt>
+ <xt><per:id></xt>1<xt></per:id></xt>
+ <xt><per:name></xt>John Smith<xt></per:name></xt>
+ <xt><per:addressBookUri></xt>http://sample/addressBook<xt></per:addressBookUri></xt>
+ <xt><per:birthDate></xt>1946-08-12T04:00:00Z<xt></per:birthDate></xt>
+ <xt><per:addresses></xt>
+ <xt><addr:address</xt> <xa>uri</xa>=<xs>'http://sample/addressBook/address/1'</xs><xt>></xt>
+ <xt><addr:personUri></xt>http://sample/addressBook/person/1<xt></addr:personUri></xt>
+ <xt><addr:id></xt>1<xt></addr:id></xt>
+ <xt><mail:street></xt>100 Main Street<xt></mail:street></xt>
+ <xt><mail:city></xt>Anywhereville<xt></mail:city></xt>
+ <xt><mail:state></xt>NY<xt></mail:state></xt>
+ <xt><mail:zip></xt>12345<xt></mail:zip></xt>
+ <xt><addr:isCurrent></xt>true<xt></addr:isCurrent></xt>
+ <xt></addr:address></xt>
+ <xt></per:addresses></xt>
+ <xt></per:person></xt>
+ </p>
+ </div>
+
+
+ <!-- ======================================================================================================== -->
+ <a id="XmlSchemaSupport"></a>
+ <h3 class='topic' onclick='toggle(this)'>2.6 - XML-Schema support</h3>
+ <div class='topic'>
+ <p>
+ Juneau provides the {@link org.apache.juneau.xml.XmlSchemaSerializer} class for generating XML-Schema documents
+ that describe the output generated by the {@link org.apache.juneau.xml.XmlSerializer} class.<br>
+ This class shares the same properties as <code>XmlSerializer</code>.<br>
+ Since the XML output differs based on settings on the XML serializer class, the XML-Schema serializer
+ class must have the same property values as the XML serializer class it's describing.<br>
+ To help facilitate creating an XML Schema serializer with the same properties as the corresponding
+ XML serializer, the {@link org.apache.juneau.xml.XmlSerializer#getSchemaSerializer()} method
+ has been added.
+ </p>
+ <p>
+ XML-Schema requires a separate file for each namespace.<br>
+ Unfortunately, does not mesh well with the Juneau serializer architecture which serializes to single writers.<br>
+ To get around this limitation, the schema serializer will produce a single output, but with multiple
+ schema documents separated by the null character (<js>'\u0000'</js>) to make it simple to split apart.
+ </p>
+ <p>
+ Lets start with an example where everything is in the same namespace.<br>
+ We'll use the classes from before, but remove the references to namespaces.<br>
+ Since we have not defined a default namespace, everything is defined under the default Juneau namespace.
+ </p>
+ <p class='bcode'>
+ <ja>@Xml</ja>(name=<js>"person"</js>)
+ <jk>public class</jk> Person {
+ <jc>// Bean properties</jc>
+ <jk>public int</jk> <jf>id</jf>;
+ <jk>public</jk> String <jf>name</jf>;
+ <ja>@BeanProperty</ja>(beanUri=<jk>true</jk>) <jk>public</jk> URI <jf>uri</jf>;
+ <jk>public</jk> URI <jf>addressBookUri</jf>;
+ <ja>@BeanProperty</ja>(transform=CalendarTransform.ISO8601DTZ.<jk>class</jk>) <jk>public</jk> Calendar <jf>birthDate</jf>;
+ <jk>public</jk> LinkedList<Address> <jf>addresses</jf> = <jk>new</jk> LinkedList<Address>();
+
+ <jc>// Bean constructor (needed by parser)</jc>
+ <jk>public</jk> Person() {}
+
+ <jc>// Normal constructor</jc>
+ <jk>public</jk> Person(<jk>int</jk> id, String name, String uri, String addressBookUri, String birthDate) <jk>throws</jk> Exception {
+ <jk>this</jk>.<jf>id</jf> = id;
+ <jk>this</jk>.<jf>name</jf> = name;
+ <jk>this</jk>.<jf>uri</jf> = <jk>new</jk> URI(uri);
+ <jk>this</jk>.<jf>addressBookUri</jf> = <jk>new</jk> URI(addressBookUri);
+ <jk>this</jk>.<jf>birthDate</jf> = <jk>new</jk> GregorianCalendar();
+ <jk>this</jk>.<jf>birthDate</jf>.setTime(DateFormat.getDateInstance(DateFormat.<jsf>MEDIUM</jsf>).parse(birthDate));
+ }
+ }
+
+ <ja>@Xml</ja>(name=<js>"address"</js>)
+ <jk>public class</jk> Address {
+ <jc>// Bean properties</jc>
+ <ja>@BeanProperty</ja>(beanUri=<jk>true</jk>) <jk>public</jk> URI <jf>uri</jf>;
+ <jk>public</jk> URI <jf>personUri</jf>;
+ <jk>public int</jk> <jf>id</jf>;
+ <jk>public</jk> String <jf>street</jf>, <jf>city</jf>, <jf>state</jf>;
+ <jk>public int</jk> <jf>zip</jf>;
+ <jk>public boolean</jk> <jf>isCurrent</jf>;
+ }
+ </p>
+ <p>
+ The code for creating our POJO model and generating XML Schema is shown below:
+ </p>
+ <p class='bcode'>
+ <jc>// Create a new serializer with readable output.</jc>
+ XmlSerializer s = <jk>new</jk> XmlSerializer()
+ .setProperty(SerializerContext.<jsf>SERIALIZER_useIndentation</jsf>, <jk>true</jk>)
+ .setProperty(XmlSerializerContext.<jsf>XML_enableNamespaces</jsf>, <jk>true</jk>)
+ .setProperty(XmlSerializerContext.<jsf>XML_addNamespaceUrisToRoot</jsf>, <jk>true</jk>)
+ .setProperty(SerializerContext.<jsf>SERIALIZER_quoteChar</jsf>, <js>'\''</js>);
+
+ <jc>// Create the equivalent schema serializer.</jc>
+ XmlSchemaSerializer ss = s.getSchemaSerializer();
+
+ <jc>// Create our bean.</jc>
+ Person p = <jk>new</jk> Person(1, <js>"John Smith"</js>, <js>"http://sample/addressBook/person/1"</js>, <js>"http://sample/addressBook"</js>, <js>"Aug 12, 1946"</js>);
+ Address a = <jk>new</jk> Address();
+ a.<jf>uri</jf> = <jk>new</jk> URI(<js>"http://sample/addressBook/address/1"</js>);
+ a.<jf>personUri</jf> = <jk>new</jk> URI(<js>"http://sample/addressBook/person/1"</js>);
+ a.<jf>id</jf> = 1;
+ a.<jf>street</jf> = <js>"100 Main Street"</js>;
+ a.<jf>city</jf> = <js>"Anywhereville"</js>;
+ a.<jf>state</jf> = <js>"NY"</js>;
+ a.<jf>zip</jf> = 12345;
+ a.<jf>isCurrent</jf> = <jk>true</jk>;
+ p.<jf>addresses</jf>.add(a);
+
+ <jc>// Serialize the bean to XML.</jc>
+ String xml = s.serialize(p);
+
+ <jc>// Get the XML Schema corresponding to the XML generated above.</jc>
+ String xmlSchema = ss.serialize(p);
+ </p>
+ <h6 class='figure'>XML results</h6>
+ <p class='bcode'>
+ <xt><person</xt>
+ <xa>xmlns</xa>=<xs>'http://www.ibm.com/2013/Juneau'</xs>
+ <xa>xmlns:xsi</xa>=<xs>'http://www.w3.org/2001/XMLSchema-instance'</xs>
+ <xa>uri</xa>=<xs>'http://sample/addressBook/person/1'</xs><xt>></xt>
+ <xt><id></xt>1<xt></id></xt>
+ <xt><name></xt>John Smith<xt></name></xt>
+ <xt><addressBookUri></xt>http://sample/addressBook<xt></addressBookUri></xt>
+ <xt><birthDate></xt>1946-08-12T00:00:00Z<xt></birthDate></xt>
+ <xt><addresses></xt>
+ <xt><address</xt> <xa>uri</xa>=<xs>'http://sample/addressBook/address/1'</xs><xt>></xt>
+ <xt><personUri></xt>http://sample/addressBook/person/1<xt></personUri></xt>
+ <xt><id></xt>1<xt></id></xt>
+ <xt><street></xt>100 Main Street<xt></street></xt>
+ <xt><city></xt>Anywhereville<xt></city></xt>
+ <xt><state></xt>NY<xt></state></xt>
+ <xt><zip></xt>12345<xt></zip></xt>
+ <xt><isCurrent></xt>true<xt></isCurrent></xt>
+ <xt></address></xt>
+ <xt></addresses></xt>
+ <xt></person></xt>
+ </p>
+ <h6 class='figure'>XML-Schema results</h6>
+ <p class='bcode'>
+ <xt><schema</xt>
+ <xa>xmlns</xa>=<xs>'http://www.w3.org/2001/XMLSchema'</xs>
+ <xa>targetNamespace</xa>=<xs>'http://www.ibm.com/2013/Juneau'</xs>
+ <xa>elementFormDefault</xa>=<xs>'qualified'</xs>
+ <xa>xmlns:juneau</xa>=<xs>'http://www.ibm.com/2013/Juneau'</xs><xt>></xt>
+ <xt><element</xt> <xa>name</xa>=<xs>'person'</xs> <xa>type</xa>=<xs>'juneau:com.ibm.sample.Person'</xs><xt>/></xt>
+ <xt><complexType</xt> <xa>name</xa>=<xs>'com.ibm.sample.Person'</xs><xt>></xt>
+ <xt><sequence></xt>
+ <xt><element</xt> <xa>name</xa>=<xs>'id'</xs> <xa>type</xa>=<xs>'integer'</xs> <xa>minOccurs</xa>=<xs>'0'</xs><xt>/></xt>
+ <xt><element</xt> <xa>name</xa>=<xs>'name'</xs> <xa>type</xa>=<xs>'string'</xs> <xa>minOccurs</xa>=<xs>'0'</xs><xt>/></xt>
+ <xt><element</xt> <xa>name</xa>=<xs>'addressBookUri'</xs> <xa>type</xa>=<xs>'string'</xs> <xa>minOccurs</xa>=<xs>'0'</xs><xt>/></xt>
+ <xt><element</xt> <xa>name</xa>=<xs>'birthDate'</xs> <xa>type</xa>=<xs>'juneau:java.util.Calendar'</xs> <xa>minOccurs</xa>=<xs>'0'</xs><xt>/></xt>
+ <xt><element</xt> <xa>name</xa>=<xs>'addresses'</xs> <xa>type</xa>=<xs>'juneau:java.util.LinkedList_x003C_com.ibm.sample.Address_x003E_'</xs> <xa>minOccurs</xa>=<xs>'0'</xs><xt>/></xt>
+ <xt></sequence></xt>
+ <xt><attribute</xt> <xa>name</xa>=<xs>'uri'</xs> <xa>type</xa>=<xs>'string'</xs><xt>/></xt>
+ <xt></complexType></xt>
+ <xt><complexType</xt> <xa>name</xa>=<xs>'java.util.Calendar'</xs><xt>></xt>
+ <xt><sequence></xt>
+ <xt><any</xt> <xa>processContents</xa>=<xs>'skip'</xs> <xa>maxOccurs</xa>=<xs>'unbounded'</xs> <xa>minOccurs</xa>=<xs>'0'</xs><xt>/></xt>
+ <xt></sequence></xt>
+ <xt></complexType></xt>
+ <xt><complexType</xt> <xa>name</xa>=<xs>'java.util.LinkedList_x003C_com.ibm.sample.Address_x003E_'</xs><xt>></xt>
+ <xt><sequence></xt>
+ <xt><choice</xt> <xa>minOccurs</xa>=<xs>'0'</xs> <xa>maxOccurs</xa>=<xs>'unbounded'</xs><xt>></xt>
+ <xt><element</xt> <xa>name</xa>=<xs>'address'</xs> <xa>type</xa>=<xs>'juneau:com.ibm.sample.Address'</xs><xt>/></xt>
+ <xt><element</xt> <xa>name</xa>=<xs>'null'</xs> <xa>type</xa>=<xs>'string'</xs><xt>/></xt>
+ <xt></choice></xt>
+ <xt></sequence></xt>
+ <xt></complexType></xt>
+ <xt><complexType</xt> <xa>name</xa>=<xs>'com.ibm.sample.Address'</xs><xt>></xt>
+ <xt><sequence></xt>
+ <xt><element</xt> <xa>name</xa>=<xs>'personUri'</xs> <xa>type</xa>=<xs>'string'</xs> <xa>minOccurs</xa>=<xs>'0'</xs><xt>/></xt>
+ <xt><element</xt> <xa>name</xa>=<xs>'id'</xs> <xa>type</xa>=<xs>'integer'</xs> <xa>minOccurs</xa>=<xs>'0'</xs><xt>/></xt>
+ <xt><element</xt> <xa>name</xa>=<xs>'street'</xs> <xa>type</xa>=<xs>'string'</xs> <xa>minOccurs</xa>=<xs>'0'</xs><xt>/></xt>
+ <xt><element</xt> <xa>name</xa>=<xs>'city'</xs> <xa>type</xa>=<xs>'string'</xs> <xa>minOccurs</xa>=<xs>'0'</xs><xt>/></xt>
+ <xt><element</xt> <xa>name</xa>=<xs>'state'</xs> <xa>type</xa>=<xs>'string'</xs> <xa>minOccurs</xa>=<xs>'0'</xs><xt>/></xt>
+ <xt><element</xt> <xa>name</xa>=<xs>'zip'</xs> <xa>type</xa>=<xs>'integer'</xs> <xa>minOccurs</xa>=<xs>'0'</xs><xt>/></xt>
+ <xt><element</xt> <xa>name</xa>=<xs>'isCurrent'</xs> <xa>type</xa>=<xs>'boolean'</xs> <xa>minOccurs</xa>=<xs>'0'</xs><xt>/></xt>
+ <xt></sequence></xt>
+ <xt><attribute</xt> <xa>name</xa>=<xs>'uri'</xs> <xa>type</xa>=<xs>'string'</xs><xt>/></xt>
+ <xt></complexType></xt>
+ <xt></schema></xt>
+ </p>
+ <p>
+ Now if we add in some namespaces, we'll see how multiple namespaces are handled.
+ </p>
+ <p class='bcode'>
+ <ja>@Xml</ja></ja>(name=<js>"person"</js>, prefix=<js>"per"</js>)
+ <jk>public class</jk> Person {
+ ...
+ }
+
+ <ja>@Xml</ja>(name=<js>"address"</js>, prefix=<js>"addr"</js>)
+ <jk>public class</jk> Address {
+ ...
+ <ja>@Xml</ja>(prefix=<js>"mail"</js>) <jk>public</jk> String <jf>street</jf>, <jf>city</jf>, <jf>state</jf>;
+ <ja>@Xml</ja>(prefix=<js>"mail"</js>) <jk>public int</jk> <jf>zip</jf>;
+ ...
+ }
+ </p>
+ <h6 class='figure'>XML results</h6>
+ <p class='bcode'>
+ <xt><per:person</xt>
+ <xa>xmlns</xa>=<xs>'http://www.ibm.com/2013/Juneau'</xs>
+ <xa>xmlns:per</xa>=<xs>'http://www.ibm.com/person/'</xs>
+ <xa>xmlns:addr</xa>=<xs>'http://www.ibm.com/address/'</xs>
+ <xa>xmlns:mail</xa>=<xs>'http://www.ibm.com/mail/'</xs>
+ <xa>xmlns:xsi</xa>=<xs>'http://www.w3.org/2001/XMLSchema-instance'</xs>
+ <xa>uri</xa>=<xs>'http://sample/addressBook/person/1'</xs><xt>></xt>
+ <xt><per:id></xt>1<xt></per:id></xt>
+ <xt><per:name></xt>John Smith<xt></per:name></xt>
+ <xt><per:addressBookUri></xt>http://sample/addressBook<xt></per:addressBookUri></xt>
+ <xt><per:birthDate></xt>1946-08-12T00:00:00Z<xt></per:birthDate></xt>
+ <xt><per:addresses></xt>
+ <xt><addr:address</xt> <xa>uri</xa>=<xs>'http://sample/addressBook/address/1'</xs><xt>></xt>
+ <xt><addr:personUri></xt>http://sample/addressBook/person/1<xt></addr:personUri></xt>
+ <xt><addr:id></xt>1<xt></addr:id></xt>
+ <xt><mail:street></xt>100 Main Street<xt></mail:street></xt>
+ <xt><mail:city></xt>Anywhereville<xt></mail:city></xt>
+ <xt><mail:state></xt>NY<xt></mail:state></xt>
+ <xt><mail:zip></xt>12345<xt></mail:zip></xt>
+ <xt><addr:isCurrent></xt>true<xt></addr:isCurrent></xt>
+ <xt></addr:address></xt>
+ <xt></per:addresses></xt>
+ <xt></per:person></xt>
+ </p>
+ <p>
+ The schema consists of 4 documents separated by a <js>'\u0000'</js> character.
+ </p>
+ <h6 class='figure'>XML-Schema results</h6>
+ <p class='bcode'>
+ <xt><schema</xt>
+ <xa>xmlns</xa>=<xs>'http://www.w3.org/2001/XMLSchema'</xs>
+ <xa>targetNamespace</xa>=<xs>'http://www.ibm.com/2013/Juneau'</xs>
+ <xa>elementFormDefault</xa>=<xs>'qualified'</xs>
+ <xa>xmlns:juneau</xa>=<xs>'http://www.ibm.com/2013/Juneau'</xs>
+ <xa>xmlns:per</xa>=<xs>'http://www.ibm.com/person/'</xs>
+ <xa>xmlns:addr</xa>=<xs>'http://www.ibm.com/address/'</xs>
+ <xa>xmlns:mail</xa>=<xs>'http://www.ibm.com/mail/'</xs><xt>></xt>
+ <xt><import</xt> <xa>namespace</xa>=<xs>'http://www.ibm.com/person/'</xs> <xa>schemaLocation</xa>=<xs>'per.xsd'</xs><xt>/></xt>
+ <xt><import</xt> <xa>namespace</xa>=<xs>'http://www.ibm.com/address/'</xs> <xa>schemaLocation</xa>=<xs>'addr.xsd'</xs><xt>/></xt>
+ <xt><import</xt> <xa>namespace</xa>=<xs>'http://www.ibm.com/mail/'</xs> <xa>schemaLocation</xa>=<xs>'mail.xsd'</xs><xt>/></xt>
+ <xt><complexType</xt> <xa>name</xa>=<xs>'int'</xs><xt>></xt>
+ <xt><simpleContent></xt>
+ <xt><extension</xt> <xa>base</xa>=<xs>'integer'</xs><xt>/></xt>
+ <xt></simpleContent></xt>
+ <xt></complexType></xt>
+ <xt><complexType</xt> <xa>name</xa>=<xs>'java.lang.String'</xs><xt>></xt>
+ <xt><simpleContent></xt>
+ <xt><extension</xt> <xa>base</xa>=<xs>'string'</xs><xt>/></xt>
+ <xt></simpleContent></xt>
+ <xt></complexType></xt>
+ <xt><complexType</xt> <xa>name</xa>=<xs>'java.net.URI'</xs><xt>></xt>
+ <xt><simpleContent></xt>
+ <xt><extension</xt> <xa>base</xa>=<xs>'string'</xs><xt>/></xt>
+ <xt></simpleContent></xt>
+ <xt></complexType></xt>
+ <xt><complexType</xt> <xa>name</xa>=<xs>'java.util.Calendar'</xs><xt>></xt>
+ <xt><sequence></xt>
+ <xt><any</xt> <xa>processContents</xa>=<xs>'skip'</xs> <xa>maxOccurs</xa>=<xs>'unbounded'</xs> <xa>minOccurs</xa>=<xs>'0'</xs><xt>/></xt>
+ <xt></sequence></xt>
+ <xt></complexType></xt>
+ <xt><complexType</xt> <xa>name</xa>=<xs>'java.util.LinkedList_x003C_com.ibm.sample.Address_x003E_'</xs><xt>></xt>
+ <xt><sequence></xt>
+ <xt><choice</xt> <xa>minOccurs</xa>=<xs>'0'</xs> <xa>maxOccurs</xa>=<xs>'unbounded'</xs><xt>></xt>
+ <xt><element</xt> <xa>name</xa>=<xs>'address'</xs> <xa>type</xa>=<xs>'addr:com.ibm.sample.Address'</xs><xt>/></xt>
+ <xt><element</xt> <xa>name</xa>=<xs>'null'</xs> <xa>type</xa>=<xs>'string'</xs><xt>/></xt>
+ <xt></choice></xt>
+ <xt></sequence></xt>
+ <xt></complexType></xt>
+ <xt><complexType</xt> <xa>name</xa>=<xs>'boolean'</xs><xt>></xt>
+ <xt><simpleContent></xt>
+ <xt><extension</xt> <xa>base</xa>=<xs>'boolean'</xs><xt>/></xt>
+ <xt></simpleContent></xt>
+ <xt></complexType></xt>
+ <xt></schema></xt>
+ [\u0000]
+ <xt><schema</xt>
+ <xa>xmlns</xa>=<xs>'http://www.w3.org/2001/XMLSchema'</xs>
+ <xa>targetNamespace</xa>=<xs>'http://www.ibm.com/person/'</xs>
+ <xa>elementFormDefault</xa>=<xs>'qualified'</xs>
+ <xa>attributeFormDefault</xa>=<xs>'qualified'</xs>
+ <xa>xmlns:juneau</xa>=<xs>'http://www.ibm.com/2013/Juneau'</xs>
+ <xa>xmlns:per</xa>=<xs>'http://www.ibm.com/person/'</xs>
+ <xa>xmlns:addr</xa>=<xs>'http://www.ibm.com/address/'</xs>
+ <xa>xmlns:mail</xa>=<xs>'http://www.ibm.com/mail/'</xs><xt>></xt>
+ <xt><impor</xt>t <xa>namespace</xa>=<xs>'http://www.ibm.com/2013/Juneau'</xs> <xa>schemaLocation</xa>=<xs>'juneau.xsd'</xs><xt>/></xt>
+ <xt><import</xt> <xa>namespace</xa>=<xs>'http://www.ibm.com/address/'</xs> <xa>schemaLocation</xa>=<xs>'addr.xsd'</xs><xt>/></xt>
+ <xt><import</xt> <xa>namespace</xa>=<xs>'http://www.ibm.com/mail/'</xs> <xa>schemaLocation</xa>=<xs>'mail.xsd'</xs><xt>/></xt>
+ <xt><element</xt> <xa>name</xa>=<xs>'person'</xs> <xa>type</xa>=<xs>'per:com.ibm.sample.Person'</xs><xt>/></xt>
+ <xt><complexType</xt> <xa>name</xa>=<xs>'com.ibm.sample.Person'</xs><xt>></xt>
+ <xt><sequence></xt>
+ <xt><any</xt> <xa>minOccurs</xa>=<xs>'0'</xs> <xa>maxOccurs</xa>=<xs>'unbounded'</xs><xt>/></xt>
+ <xt></sequence></xt>
+ <xt><attribute</xt> <xa>name</xa>=<xs>'uri'</xs> <xa>type</xa>=<xs>'string'</xs><xt>/></xt>
+ <xt></complexType></xt>
+ <xt><element</xt> <xa>name</xa>=<xs>'id'</xs> <xa>type</xa>=<xs>'juneau:int'</xs><xt>/></xt>
+ <xt><element</xt> <xa>name</xa>=<xs>'name'</xs> <xa>type</xa>=<xs>'juneau:java.lang.String'</xs><xt>/></xt>
+ <xt><element</xt> <xa>name</xa>=<xs>'addressBookUri'</xs> <xa>type</xa>=<xs>'juneau:java.net.URI'</xs><xt>/></xt>
+ <xt><element</xt> <xa>name</xa>=<xs>'birthDate'</xs> <xa>type</xa>=<xs>'juneau:java.util.Calendar'</xs><xt>/></xt>
+ <xt><element</xt> <xa>name</xa>=<xs>'addresses'</xs> <xa>type</xa>=<xs>'juneau:java.util.LinkedList_x003C_com.ibm.sample.Address_x003E_'</xs><xt>/></xt>
+ <xt></schema></xt>
+ [\u0000]
+ <xt><schema</xt>
+ <xa>xmlns</xa>=<xs>'http://www.w3.org/2001/XMLSchema'</xs>
+ <xa>targetNamespace</xa>=<xs>'http://www.ibm.com/address/'</xs>
+ <xa>elementFormDefault</xa>=<xs>'qualified'</xs>
+ <xa>attributeFormDefault</xa>=<xs>'qualified'</xs>
+ <xa>xmlns:juneau</xa>=<xs>'http://www.ibm.com/2013/Juneau'</xs>
+ <xa>xmlns:per</xa>=<xs>'http://www.ibm.com/person/'</xs>
+ <xa>xmlns:addr</xa>=<xs>'http://www.ibm.com/address/'</xs>
+ <xa>xmlns:mail</xa>=<xs>'http://www.ibm.com/mail/'</xs><xt>></xt>
+ <xt><import</xt> <xa>namespace</xa>=<xs>'http://www.ibm.com/2013/Juneau'</xs> <xa>schemaLocation</xa>=<xs>'juneau.xsd'</xs><xt>/></xt>
+ <xt><import</xt> <xa>namespace</xa>=<xs>'http://www.ibm.com/person/'</xs> <xa>schemaLocation</xa>=<xs>'per.xsd'</xs><xt>/></xt>
+ <xt><import</xt> <xa>namespace</xa>=<xs>'http://www.ibm.com/mail/'</xs> <xa>schemaLocation</xa>=<xs>'mail.xsd'</xs><xt>/></xt>
+ <xt><complexType</xt> <xa>name</xa>=<xs>'com.ibm.sample.Address'</xs><xt>></xt>
+ <xt><sequence></xt>
+ <xt><any</xt> <xa>minOccurs</xa>=<xs>'0'</xs> <xa>maxOccurs</xa>=<xs>'unbounded'</xs><xt>/></xt>
+ <xt></sequence></xt>
+ <xt><attribute</xt> <xa>name</xa>=<xs>'uri'</xs> <xa>type</xa>=<xs>'string'</xs><xt>/></xt>
+ <xt></complexType></xt>
+ <xt><element</xt> <xa>name</xa>=<xs>'personUri'</xs> <xa>type</xa>=<xs>'juneau:java.net.URI'</xs><xt>/></xt>
+ <xt><element</xt> <xa>name</xa>=<xs>'id'</xs> <xa>type</xa>=<xs>'juneau:int'</xs><xt>/></xt>
+ <xt><element</xt> <xa>name</xa>=<xs>'isCurrent'</xs> <xa>type</xa>=<xs>'juneau:boolean'</xs><xt>/></xt>
+ <xt></schema></xt>
+ [\u0000]
+ <xt><schema</xt>
+ <xa>xmlns</xa>=<xs>'http://www.w3.org/2001/XMLSchema'</xs>
+ <xa>targetNamespace</xa>=<xs>'http://www.ibm.com/mail/'</xs>
+ <xa>elementFormDefault</xa>=<xs>'qualified'</xs>
+ <xa>attributeFormDefault</xa>=<xs>'qualified'</xs>
+ <xa>xmlns:juneau</xa>=<xs>'http://www.ibm.com/2013/Juneau'</xs>
+ <xa>xmlns:per</xa>=<xs>'http://www.ibm.com/person/'</xs>
+ <xa>xmlns:addr</xa>=<xs>'http://www.ibm.com/address/'</xs>
+ <xa>xmlns:mail</xa>=<xs>'http://www.ibm.com/mail/'</xs><xt>></xt>
+ <xt><import</xt> <xa>namespace</xa>=<xs>'http://www.ibm.com/2013/Juneau'</xs> <xa>schemaLocation</xa>=<xs>'juneau.xsd'</xs><xt>/></xt>
+ <xt><import</xt> <xa>namespace</xa>=<xs>'http://www.ibm.com/person/'</xs> <xa>schemaLocation</xa>=<xs>'per.xsd'</xs><xt>/></xt>
+ <xt><import</xt> <xa>namespace</xa>=<xs>'http://www.ibm.com/address/'</xs> <xa>schemaLocation</xa>=<xs>'addr.xsd'</xs><xt>/></xt>
+ <xt><element</xt> <xa>name</xa>=<xs>'street'</xs> <xa>type</xa>=<xs>'juneau:java.lang.String'</xs><xt>/></xt>
+ <xt><element</xt> <xa>name</xa>=<xs>'city'</xs> <xa>type</xa>=<xs>'juneau:java.lang.String'</xs><xt>/></xt>
+ <xt><element</xt> <xa>name</xa>=<xs>'state'</xs> <xa>type</xa>=<xs>'juneau:java.lang.String'</xs><xt>/></xt>
+ <xt><element</xt> <xa>name</xa>=<xs>'zip'</xs> <xa>type</xa>=<xs>'juneau:int'</xs><xt>/></xt>
+ <xt></schema></xt>
+ </p>
+ <p>
+ For convenience, the {@link org.apache.juneau.xml.XmlSchemaSerializer#getValidator(SerializerSession,Object)} method is provided
+ to create a {@link javax.xml.validation.Validator} using the input from the serialize method.
+ </p>
+ </div>
+
+
+ <!-- ======================================================================================================== -->
+ <a id="Recursion"></a>
+ <h3 class='topic' onclick='toggle(this)'>2.7 - Non-tree models and recursion detection</h3>
+ <div class='topic'>
+ <p>
+ The XML serializer is designed to be used against POJO tree structures. <br>
+ It expects that there not be loops in the POJO model (e.g. children with references to parents, etc...).<br>
+ If you try to serialize models with loops, you will usually cause a <code>StackOverflowError</code> to
+ be thrown (if {@link org.apache.juneau.serializer.SerializerContext#SERIALIZER_maxDepth} is not reached first).
+ </p>
+ <p>
+ If you still want to use the XML serializer on such models, Juneau provides the
+ {@link org.apache.juneau.serializer.SerializerContext#SERIALIZER_detectRecursions} setting.<br>
+ It tells the serializer to look for instances of an object in the current branch of the tree and
+ skip serialization when a duplicate is encountered.
+ </p>
+ <p>
+ For example, let's make a POJO model out of the following classes:
+ </p>
+ <p class='bcode'>
+ <ja>@Xml</ja>(name=<js>"a"</js>)
+ <jk>public class</jk> A {
+ <jk>public</jk> B b;
+ }
+
+ <jk>public class</jk> B {
+ <jk>public</jk> C c;
+ }
+
+ <jk>public class</jk> C {
+ <jk>public</jk> A a;
+ }
+ </p>
+ <p>
+ Now we create a model with a loop and serialize the results.
+ </p>
+ <p class='bcode'>
+ <jc>// Create a new serializer with readable output.</jc>
+ XmlSerializer s = <jk>new</jk> XmlSerializer()
+ .setProperty(SerializerContext.<jsf>SERIALIZER_useIndentation</jsf>, <jk>true</jk>)
+ .setProperty(SerializerContext.<jsf>SERIALIZER_quoteChar</jsf>, <js>'\''</js>)
+ .setProperty(XmlSerializerContext.<jsf>XML_enableNamespaces</jsf>, <jk>false</jk>)
+ .setProperty(SerializerContext.<jsf>SERIALIZER_detectRecursions</jsf>, <jk>true</jk>);
+
+ <jc>// Create a recursive loop.</jc>
+ A a = <jk>new</jk> A();
+ a.<jf>b</jf> = <jk>new</jk> B();
+ a.<jf>b</jf>.<jf>c</jf> = <jk>new</jk> C();
+ a.<jf>b</jf>.<jf>c</jf>.<jf>a</jf> = a;
+
+ <jc>// Serialize to XML.</jc>
+ String xml = s.serialize(a);
+ </p>
+ <p>
+ What we end up with is the following, which does not serialize the contents of the <code>c</code> field:
+ </p>
+ <p class='bcode'>
+ <xt><a></xt>
+ <xt><b></xt>
+ <xt><c/></xt>
+ <xt></b></xt>
+ <xt></a></xt>
+ </p>
+ <p>
+ Without recursion detection enabled, this would cause a stack-overflow error.
+ </p>
+ <p>
+ Recursion detection introduces a performance penalty of around 20%.<br>
+ For this reason the setting is disabled by default.
+ </p>
+ </div>
+
+
+ <!-- ======================================================================================================== -->
+ <a id="SerializerConfigurableProperties"></a>
+ <h3 class='topic' onclick='toggle(this)'>2.8 - Configurable properties</h3>
+ <div class='topic'>
+ <p>
+ See the following classes for all configurable properties that can be used on this serializer:
+ </p>
+ <ul>
+ <li>{@link org.apache.juneau.BeanContext} - Bean context properties.
+ <li>{@link org.apache.juneau.xml.XmlSerializerContext} - Serializer context properties.
+ </ul>
+ </div>
+
+
+ <!-- ======================================================================================================== -->
+ <a id="SerializerOtherNotes"></a>
+ <h3 class='topic' onclick='toggle(this)'>2.9 - Other notes</h3>
+ <div class='topic'>
+ <ul class='spaced-list'>
+ <li>Like all other Juneau serializers, the XML serializer is thread safe and maintains an internal cache of bean classes encountered.<br>
+ For performance reasons, it's recommended that serializers be reused whenever possible instead of always creating new instances.
+ </ul>
+ </div>
+</div>
+
+
+<!-- ======================================================================================================== -->
+<a id="XmlParser"></a>
+<h2 class='topic' onclick='toggle(this)'>3 - XmlParser class</h2>
+<div class='topic'>
+ <p>
+ The {@link org.apache.juneau.xml.XmlParser} class is the class used to parse Juneau-generated XML back into POJOs.
+ </p>
+ <p>
+ A static reusable instance of <code>XmlParser</code> is also provided for convenience:
+ </p>
+ <ul>
+ <li>{@link org.apache.juneau.xml.XmlParser#DEFAULT}
+ </ul>
+ <p>
+ Let's build upon the previous example and parse the generated XML back into the original bean.<br>
+ We start with the XML that was generated.
+ </p>
+ <p class='bcode'>
+ <jc>// Create a new serializer with readable output.</jc>
+ XmlSerializer s = <jk>new</jk> XmlSerializer()
+ .setProperty(SerializerContext.<jsf>SERIALIZER_useIndentation</jsf>, <jk>true</jk>)
+ .setProperty(SerializerContext.<jsf>SERIALIZER_quoteChar</jsf>, <js>'\''</js>);
+
+ <jc>// Create our bean.</jc>
+ Person p = <jk>new</jk> Person(1, <js>"John Smith"</js>, <js>"http://sample/addressBook/person/1"</js>, <js>"http://sample/addressBook"</js>, <js>"Aug 12, 1946"</js>);
+ Address a = <jk>new</jk> Address();
+ a.<jf>uri</jf> = <jk>new</jk> URI(<js>"http://sample/addressBook/address/1"</js>);
+ a.<jf>personUri</jf> = <jk>new</jk> URI(<js>"http://sample/addressBook/person/1"</js>);
+ a.<jf>id</jf> = 1;
+ a.<jf>street</jf> = <js>"100 Main Street"</js>;
+ a.<jf>city</jf> = <js>"Anywhereville"</js>;
+ a.<jf>state</jf> = <js>"NY"</js>;
+ a.<jf>zip</jf> = 12345;
+ a.<jf>isCurrent</jf> = <jk>true</jk>;
+ p.<jf>addresses</jf>.add(a);
+
+ <jc>// Serialize the bean to XML.</jc>
+ String xml = s.serialize(p);
+ </p>
+ <p>
+ This code produced the following:
+ </p>
+ <p class='bcode'>
+ <xt><per:person</xt>
+ <xa>xmlns</xa>=<xs>'http://www.ibm.com/2013/Juneau'</xs>
+ <xa>xmlns:per</xa>=<xs>'http://www.ibm.com/person/'</xs>
+ <xa>xmlns:addr</xa>=<xs>'http://www.ibm.com/address/'</xs>
+ <xa>xmlns:mail</xa>=<xs>'http://www.ibm.com/mail/'</xs>
+ <xa>xmlns:xsi</xa>=<xs>'http://www.w3.org/2001/XMLSchema-instance'</xs>
+ <xa>uri</xa>=<xs>'http://sample/addressBook/person/1'</xs><xt>></xt>
+ <xt><per:id></xt>1<xt></per:id></xt>
+ <xt><per:name></xt>John Smith<xt></per:name></xt>
+ <xt><per:addressBookUri></xt>http://sample/addressBook<xt></per:addressBookUri></xt>
+ <xt><per:birthDate></xt>1946-08-12T04:00:00Z<xt></per:birthDate></xt>
+ <xt><per:addresses></xt>
+ <xt><addr:address</xt> <xa>uri</xa>=<xs>'http://sample/addressBook/address/1'</xs><xt>></xt>
+ <xt><addr:personUri></xt>http://sample/addressBook/person/1<xt></addr:personUri></xt>
+ <xt><addr:id></xt>1<xt></addr:id></xt>
+ <xt><mail:street></xt>100 Main Street<xt></mail:street></xt>
+ <xt><mail:city></xt>Anywhereville<xt></mail:city></xt>
+ <xt><mail:state></xt>NY<xt></mail:state></xt>
+ <xt><mail:zip></xt>12345<xt></mail:zip></xt>
+ <xt><addr:isCurrent></xt>true<xt></addr:isCurrent></xt>
+ <xt></addr:address></xt>
+ <xt></per:addresses></xt>
+ <xt></per:person></xt>
+ </p>
+ <p>
+ The code to convert this back into a bean is:
+ </p>
+ <p class='bcode'>
+ <jc>// Parse it back into a bean using the reusable XML parser.</jc>
+ Person p = XmlParser.<jsf>DEFAULT</jsf>.parse(xml, Person.<jk>class</jk>);
+
+ <jc>// Render it as JSON.</jc>
+ String json = JsonSerializer.<jsf>DEFAULT_LAX_READABLE</jsf>.serialize(p);
+ </p>
+ <p>
+ We print it out to JSON to show that all the data has been preserved:
+ </p>
+ <p class='bcode'>
+ {
+ id: 1,
+ name: <js>'John Smith'</js>,
+ uri: <js>'http://sample/addressBook/person/1'</js>,
+ addressBookUri: <js>'http://sample/addressBook'</js>,
+ birthDate: <js>'1946-08-12T00:00:00Z'</js>,
+ addresses: [
+ {
+ uri: <js>'http://sample/addressBook/address/1'</js>,
+ personUri: <js>'http://sample/addressBook/person/1'</js>,
+ id: 1,
+ street: <js>'100 Main Street'</js>,
+ city: <js>'Anywhereville'</js>,
+ state: <js>'NY'</js>,
+ zip: 12345,
+ isCurrent: <jk>true</jk>
+ }
+ ]
+ }
+ </p>
+
+
+ <!-- ======================================================================================================== -->
+ <a id="GenericParsing"></a>
+ <h3 class='topic' onclick='toggle(this)'>3.1 - Parsing into generic POJO models</h3>
+ <div class='topic'>
+ <p>
+ The XML parser is not limited to parsing back into the original bean classes.<br>
+ If the bean classes are not available on the parsing side, the parser can also be used to
+ parse into a generic model consisting of <code>Maps</code>, <code>Collections</code>, and primitive
+ objects.
+ </p>
+ <p>
+ You can parse into any <code>Map</code> type (e.g. <code>HashMap</code>, <code>TreeMap</code>), but
+ using {@link org.apache.juneau.ObjectMap} is recommended since it has many convenience methods
+ for converting values to various types.<br>
+ The same is true when parsing collections. You can use any Collection (e.g. <code>HashSet</code>, <code>LinkedList</code>)
+ or array (e.g. <code>Object[]</code>, <code>String[]</code>, <code>String[][]</code>), but using
+ {@link org.apache.juneau.ObjectList} is recommended.
+ </p>
+ <p>
+ When the map or list type is not specified, or is the abstract <code>Map</code>, <code>Collection</code>, or <code>List</code> types,
+ the parser will use <code>ObjectMap</code> and <code>ObjectList</code> by default.
+ </p>
+
+
+ <!-- ======================================================================================================== -->
+ <a id="AddJsonTypeAttr"></a>
+ <h3 class='topic' onclick='toggle(this)'>3.1.1 - Serializing with JSON-type attributes</h3>
+ <div class='topic'>
+ <p>
+ In some circumstances, the XML parser needs additional information to recreate the original
+ data structure when various annotations (e.g. {@link org.apache.juneau.xml.annotation.Xml#childName()}, {@link org.apache.juneau.xml.annotation.Xml#format()})
+ are used.
+ </p>
+ <p>
+ For example, starting with this XML:
+ </p>
+ <p class='bcode'>
+ <xt><per:person</xt>
+ <xa>xmlns</xa>=<xs>'http://www.ibm.com/2013/Juneau'</xs>
+ <xa>xmlns:per</xa>=<xs>'http://www.ibm.com/person/'</xs>
+ <xa>xmlns:addr</xa>=<xs>'http://www.ibm.com/address/'</xs>
+ <xa>xmlns:mail</xa>=<xs>'http://www.ibm.com/mail/'</xs>
+ <xa>xmlns:xsi</xa>=<xs>'http://www.w3.org/2001/XMLSchema-instance'</xs>
+ <xa>uri</xa>=<xs>'http://sample/addressBook/person/1'</xs><xt>></xt>
+ <xt><per:id></xt>1<xt></per:id></xt>
+ <xt><per:name></xt>John Smith<xt></per:name></xt>
+ <xt><per:addressBookUri></xt>http://sample/addressBook<xt></per:addressBookUri></xt>
+ <xt><per:birthDate></xt>1946-08-12T04:00:00Z<xt></per:birthDate></xt>
+ <xt><per:addresses></xt>
+ <xt><addr:address</xt> <xa>uri</xa>=<xs>'http://sample/addressBook/address/1'</xs><xt>></xt>
+ <xt><addr:personUri></xt>http://sample/addressBook/person/1<xt></addr:personUri></xt>
+ <xt><addr:id></xt>1<xt></addr:id></xt>
+ <xt><mail:street></xt>100 Main Street<xt></mail:street></xt>
+ <xt><mail:city></xt>Anywhereville<xt></mail:city></xt>
+ <xt><mail:state></xt>NY<xt></mail:state></xt>
+ <xt><mail:zip></xt>12345<xt></mail:zip></xt>
+ <xt><addr:isCurrent></xt>true<xt></addr:isCurrent></xt>
+ <xt></addr:address></xt>
+ <xt></per:addresses></xt>
+ <xt></per:person></xt>
+ </p>
+ <p>
+ Let's try to parse this into an <code>ObjectMap</code>.
+ </p>
+ <p class='bcode'>
+ <jc>// Parse XML into a generic POJO model.</jc>
+ ObjectMap m = XmlParser.<jsf>DEFAULT</jsf>.parse(xml, ObjectMap.<jk>class</jk>);
+
+ <jc>// Convert it to JSON.</jc>
+ String json = JsonSerializer.<jsf>DEFAULT_LAX_READABLE</jsf>.serialize(m);
+ </p>
+ <p>
+ What we end up with is the following:
+ </p>
+ <p class='bcode'>
+ {
+ uri: <js>'http://sample/addressBook/person/1'</js>,
+ id: <js>'1'</js>,
+ name: <js>'John Smith'</js>,
+ addressBookUri: <js>'http://sample/addressBook'</js>,
+ birthDate: <js>'1946-08-12T04:00:00Z'</js>,
+ addresses: {
+ address: {
+ uri: <js>'http://sample/addressBook/address/1'</js>,
+ personUri: <js>'http://sample/addressBook/person/1'</js>,
+ id: <js>'1'</js>,
+ street: <js>'100 Main Street'</js>,
+ city: <js>'Anywhereville'</js>,
+ state: <js>'NY'</js>,
+ zip: <js>'12345'</js>,
+ isCurrent: <js>'true'</js>
+ }
+ }
+ }
+ </p>
+ <p>
+ Note that the addresses field does not parse correctly as an array of addresses.<br>
+ Without the beans providing meta-information about the data structure, the XML
+ parser has no way of determining that it's an array.
+ </p>
+ <p>
+ To preserve this information, the {@link org.apache.juneau.xml.XmlSerializerContext#XML_addJsonTypeAttrs XML_addJsonTypeAttrs} property
+ is provided that will insert <xa>type</xa> attributes into the XML to preserve JSON equivalency in the document when it cannot be determined automatically.
+ </p>
+ <h6 class='figure'>Example with XML_addJsonTypeAttrs setting enabled</h6>
+ <p class='bcode'>
+ <jc>// Create a new serializer with readable output.</jc>
+ XmlSerializer s = <jk>new</jk> XmlSerializer()
+ .setProperty(SerializerContext.<jsf>SERIALIZER_useIndentation</jsf>, <jk>true</jk>)
+ .setProperty(SerializerContext.<jsf>SERIALIZER_quoteChar</jsf>, <js>'\''</js>)
+ .setProperty(XmlSerializerContext.<jsf>XML_addJsonTypeAttrs</jsf>, <jk>true</jk>);
+ </p>
+ <h6 class='figure'>Results</h6>
+ <p class='bcode'>
+ <xt><per:person</xt>
+ <xa>xmlns</xa>=<xs>'http://www.ibm.com/2013/Juneau'</xs>
+ <xa>xmlns:per</xa>=<xs>'http://www.ibm.com/person/'</xs>
+ <xa>xmlns:addr</xa>=<xs>'http://www.ibm.com/address/'</xs>
+ <xa>xmlns:mail</xa>=<xs>'http://www.ibm.com/mail/'</xs>
+ <xa>xmlns:xsi</xa>=<xs>'http://www.w3.org/2001/XMLSchema-instance'</xs>
+ <xa>uri</xa>=<xs>'http://sample/addressBook/person/1'</xs><xt>></xt>
+ <xt><per:id</xt> <xa>type</xa>=<xs>'number'</xs><xt>></xt>1<xt></per:id></xt>
+ <xt><per:name></xt>John Smith<xt></per:name></xt>
+ <xt><per:addressBookUri></xt>http://sample/addressBook<xt></per:addressBookUri></xt>
+ <xt><per:birthDate></xt>1946-08-12T04:00:00Z<xt></per:birthDate></xt>
+ <xt><per:addresses</xt> <xa>type</xa>=<xs>'array'</xs><xt>></xt>
+ <xt><addr:address</xt> <xa>uri</xa>=<xs>'http://sample/addressBook/address/1'</xs><xt>></xt>
+ <xt><addr:personUri></xt>http://sample/addressBook/person/1<xt></addr:personUri></xt>
+ <xt><addr:id</xt> <xa>type</xa>=<xs>'number'</xs><xt>></xt>1<xt></addr:id></xt>
+ <xt><mail:street></xt>100 Main Street<xt></mail:street></xt>
+ <xt><mail:city></xt>Anywhereville<xt></mail:city></xt>
+ <xt><mail:state></xt>NY<xt></mail:state></xt>
+ <xt><mail:zip</xt> <xa>type</xa>=<xs>'number'</xs><xt>></xt>12345<xt></mail:zip></xt>
+ <xt><addr:isCurrent</xt> <xa>type</xa>=<xs>'boolean'</xs><xt>></xt>true<xt></addr:isCurrent></xt>
+ <xt></addr:address></xt>
+ <xt></per:addresses></xt>
+ <xt></per:person></xt>
+ </p>
+ <p>
+ Notice the various <xa>type</xa> attributes that have been added to the output.
+ </p>
+ <p>
+ Now when we parse this into an <code>ObjectMap</code> and serialize it to JSON, we get the following:
+ </p>
+ <p class='bcode'>
+ {
+ uri: <js>'http://sample/addressBook/person/1'</js>,
+ id: <jk>1</jk>,
+ name: <js>'John Smith'</js>,
+ addressBookUri: <js>'http://sample/addressBook'</js>,
+ birthDate: <js>'1946-08-12T04:00:00Z'</js>,
+ addresses: [
+ {
+ uri: <js>'http://sample/addressBook/address/1'</js>,
+ personUri: <js>'http://sample/addressBook/person/1'</js>,
+ id: <jk>1</jk>,
+ street: <js>'100 Main Street'</js>,
+ city: <js>'Anywhereville'</js>,
+ state: <js>'NY'</js>,
+ zip: <jk>12345</jk>,
+ isCurrent: <jk>true</jk>
+ }
+ ]
+ }
+ </p>
+ <p>
+ Once parsed into a generic model, various convenience methods are provided on the <code>ObjectMap</code>
+ and <code>ObjectList</code> classes to retrieve values:
+ </p>
+ <p class='bcode'>
+ <jc>// Parse XML into a generic POJO model.</jc>
+ ObjectMap m = XmlParser.<jsf>DEFAULT</jsf>.parse(xml, ObjectMap.<jk>class</jk>);
+
+ <jc>// Get some simple values.</jc>
+ String name = m.getString(<js>"name"</js>);
+ <jk>int</jk> id = m.getInt(<js>"id"</js>);
+
+ <jc>// Get a value convertable from a String.</jc>
+ URI uri = m.get(URI.<jk>class</jk>, <js>"uri"</js>);
+
+ <jc>// Get a value using a transform.</jc>
+ CalendarTransform transform = <jk>new</jk> CalendarTransform.ISO8601DTZ();
+ Calendar birthDate = m.get(transform, <js>"birthDate"</js>);
+
+ <jc>// Get the addresses.</jc>
+ ObjectList addresses = m.getObjectList(<js>"addresses"</js>);
+
+ <jc>// Get the first address and convert it to a bean.</jc>
+ Address address = addresses.get(Address.<jk>class</jk>, 0);
+ </p>
+ </div>
+
+ <p>
+ As a general rule, parsing into beans is often more efficient than parsing into generic models.<br>
+ And working with beans is often less error prone than working with generic models.
+ </p>
+ </div>
+
+ <!-- ======================================================================================================== -->
+ <a id="ParserConfigurableProperties"></a>
+ <h3 class='topic' onclick='toggle(this)'>3.2 - Configurable properties</h3>
+ <div class='topic'>
+ <p>
+ See the following classes for all configurable properties that can be used on this parser:
+ </p>
+ <ul>
+ <li>{@link org.apache.juneau.BeanContext} - Bean context properties.
+ <li>{@link org.apache.juneau.xml.XmlParserContext} - Parser context properties.
+ </ul>
+ </div>
+
+
+ <!-- ======================================================================================================== -->
+ <a id="ParserOtherNotes"></a>
+ <h3 class='topic' onclick='toggle(this)'>3.3 - Other notes</h3>
+ <div class='topic'>
+ <ul class='spaced-list'>
+ <li>Like all other Juneau parsers, the XML parser is thread safe and maintains an internal cache of bean classes encountered.<br>
+ For performance reasons, it's recommended that parser be reused whenever possible instead of always creating new instances.
+ </ul>
+ </div>
+
+</div>
+
+
+<!-- ======================================================================================================== -->
+<a id="RestApiSupport"></a>
+<h2 class='topic' onclick='toggle(this)'>4 - REST API support</h2>
+<div class='topic'>
+ <p>
+ Juneau provides fully-integrated support for XML serialization/parsing in the REST server and client APIs.<br>
+ The next two sections describe these in detail.
+ </p>
+
+ <!-- ======================================================================================================== -->
+ <a id="RestServerSupport"></a>
+ <h3 class='topic' onclick='toggle(this)'>4.1 - REST server support</h3>
+ <div class='topic'>
+ <p>
+ There are four general ways of defining REST interfaces with support for XML.
+ Two using the built-in Juneau Server API, and two using the JAX-RS integration component.
+ </p>
+ <ul class='spaced-list'>
+ <li>Create a servlet that subclasses from {@link org.apache.juneau.server.RestServletDefault}.<br>
+ This includes XML serialization/parsing support by default, in addition to several other media types.
+ <li>Create a servlet that subclasses from {@link org.apache.juneau.server.RestServlet} and specify the
+ an XML serializer and/or parser using the {@link org.apache.juneau.server.annotation.RestResource#serializers()} and
+ {@link org.apache.juneau.server.annotation.RestRe
<TRUNCATED>