| <!-- |
| /*************************************************************************************************************************** |
| * 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. |
| ***************************************************************************************************************************/ |
| --> |
| |
| Namespaces |
| |
| <p> |
| Let's go back to the example of our original <c>Person</c> bean class, but add some namespace annotations: |
| </p> |
| <h5 class='figure'>Sample Beans</h5> |
| <p class='bpcode w800'> |
| <ja>@Xml</ja>(prefix=<js>"per"</js>) |
| <ja>@Bean</ja>(typeName=<js>"person"</js>) |
| <jk>public class</jk> Person { |
| |
| <jc>// Bean properties</jc> |
| <jk>public</jk> String <jf>name</jf>; |
| <ja>@Swap</ja>(TemporalCalendarSwap.IsoInstant.<jk>class</jk>) <jk>public</jk> Calendar <jf>birthDate</jf>; |
| <jk>public</jk> List<Address> <jf>addresses</jf>; |
| |
| <jc>// Getters/setters omitted</jc> |
| } |
| |
| <ja>@Xml</ja>(prefix=<js>"addr"</js>) |
| <ja>@Bean</ja>(typeName=<js>"address"</js>) |
| <jk>public class</jk> Address { |
| |
| <jc>// Bean properties</jc> |
| <ja>@Xml</ja>(prefix=<js>"mail"</js>) <jk>public</jk> String <jf>street</jf>, <jf>city</jf>; |
| <ja>@Xml</ja>(prefix=<js>"mail"</js>) <jk>public</jk> StateEnum <jf>state</jf>; |
| <ja>@Xml</ja>(prefix=<js>"mail"</js>) <jk>public int</jk> <jf>zip</jf>; |
| <jk>public boolean</jk> <jf>isCurrent</jf>; |
| |
| <jc>// Getters/setters omitted</jc> |
| } |
| </p> |
| <p> |
| The namespace URLs can either be defined as part of the {@link oaj.xml.annotation.Xml @Xml} |
| annotation, or can be defined at the package level with the {@link oaj.xml.annotation.XmlSchema @XmlSchema} |
| annotation. |
| Below shows it defined at the package level: |
| </p> |
| <h5 class='figure'>package-info.java</h5> |
| <p class='bpcode w800'> |
| <ja>@XmlSchema</ja>( |
| prefix=<js>"ab"</js>, <jc>// Default namespace</jc> |
| xmlNs={ |
| <ja>@XmlNs</ja>(prefix=<js>"ab"</js>, namespaceURI=<js>"http://www.apache.org/addressBook/"</js>), |
| <ja>@XmlNs</ja>(prefix=<js>"per"</js>, namespaceURI=<js>"http://www.apache.org/person/"</js>), |
| <ja>@XmlNs</ja>(prefix=<js>"addr"</js>, namespaceURI=<js>"http://www.apache.org/address/"</js>), |
| <ja>@XmlNs</ja>(prefix=<js>"mail"</js>, namespaceURI=<js>"http://www.apache.org/mail/"</js>) |
| } |
| ) |
| <jk>package</jk> org.apache.juneau.examples.addressbook; |
| </p> |
| <h5 class='figure'>Sample Code</h5> |
| <p class='bpcode w800'> |
| Person p = <jk>new</jk> Person() |
| .name(<js>"John Smith"</js>) |
| .birthDate(<js>"1946-08-12T00:00:00Z"</js>) |
| .addresses( |
| <jk>new</jk> Address() |
| .street(<js>"100 Main Street"</js>) |
| .city(<js>"Anywhereville"</js>) |
| .state(<jsf>NY</jsf>) |
| .zip(12345) |
| .isCurrent(<jk>true</jk>); |
| ); |
| |
| <jc>// Create a new serializer with readable output, this time with namespaces enabled.</jc> |
| <jc>// Note that this is identical to XmlSerializer.DEFAULT_NS_SQ_READABLE.</jc> |
| XmlSerializer s = XmlSerializer.<jsm>create</jsm>().ns().ws().sq().build(); |
| |
| String xml = s.serialize(p); |
| </p> |
| <p> |
| Now when we run this code, we'll see namespaces added to our output: |
| </p> |
| <p class='bpcode w800'> |
| <xt><per:person></xt> |
| <xt><per:name></xt>John Smith<xt></per:name></xt> |
| <xt><per:birthDate></xt>1946-08-12T04:00:00Z<xt></per:birthDate></xt> |
| <xt><per:addresses></xt> |
| <xt><addr:address></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> |
| Enabling the {@link oaj.xml.XmlSerializer#XML_addNamespaceUrisToRoot} setting results |
| in the namespace URLs being added to the root node: |
| </p> |
| <p class='bpcode w800'> |
| <xt><per:person</xt> |
| <xa>xmlns</xa>=<xs>'http://www.apache.org/2013/Juneau'</xs> |
| <xa>xmlns:per</xa>=<xs>'http://www.apache.org/person/'</xs> |
| <xa>xmlns:addr</xa>=<xs>'http://www.apache.org/address/'</xs> |
| <xa>xmlns:mail</xa>=<xs>'http://www.apache.org/mail/'</xs> |
| <xt>></xt> |
| <xt><per:name></xt>John Smith<xt></per:name></xt> |
| <xt><per:birthDate></xt>1946-08-12T04:00:00Z<xt></per:birthDate></xt> |
| <xt><per:addresses></xt> |
| <xt><addr:address></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> |
| 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='bpcode w800'> |
| <jc>// Create a new serializer with readable output, this time with namespaces enabled.</jc> |
| XmlSerializer s = XmlSerializer.<jsm>create</jsm>().ws().sq().ns() |
| .defaultNamespaceUri(<js>"http://www.apache.org/person/"</js>) |
| .build(); |
| </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='bpcode w800'> |
| <xt><person</xt> |
| <xa>xmlns:juneau</xa>=<xs>'http://www.apache.org/2013/Juneau'</xs> |
| <xa>xmlns</xa>=<xs>'http://www.apache.org/person/'</xs> |
| <xa>xmlns:addr</xa>=<xs>'http://www.apache.org/address/'</xs> |
| <xa>xmlns:mail</xa>=<xs>'http://www.apache.org/mail/'</xs> |
| <xt>></xt> |
| <xt><name></xt>John Smith<xt></name></xt> |
| <xt><birthDate></xt>1946-08-12T04:00:00Z<xt></birthDate></xt> |
| <xt><addresses></xt> |
| <xt><addr:address></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></addresses></xt> |
| <xt></person></xt> |
| </p> |
| <p> |
| One important property on the XML serializer class is |
| {@link oaj.xml.XmlSerializer#XML_autoDetectNamespaces XML_autoDetectNamespaces}. |
| This property tells the serializer to make a first-pass over the data structure to look for namespaces |
| defined on classes and bean properties. |
| 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 pre-scan step. |
| </p> |
| <p class='bpcode w800'> |
| <jc>// Create a new serializer with readable output, this time with namespaces enabled.</jc> |
| XmlSerializer s = XmlSerializer.<jsm>create</jsm>() |
| .ws() |
| .sq() |
| .autoDetectNamespaces(<jk>false</jk>) |
| .namespaces(<js>"{per:'http://www.apache.org/person/'}"</js>) |
| .build(); |
| </p> |