Namespaces

Let's go back to the example of our original Person bean class, but add some namespace annotations:

##### Sample Beans

@Xml(prefix="per") @Bean(typeName="person") public class Person { // Bean properties public String name; @Swap(TemporalCalendarSwap.IsoInstant.class) public Calendar birthDate; public List<Address> addresses; // Getters/setters omitted } @Xml(prefix="addr") @Bean(typeName="address") public class Address { // Bean properties @Xml(prefix="mail") public String street, city; @Xml(prefix="mail") public StateEnum state; @Xml(prefix="mail") public int zip; public boolean isCurrent; // Getters/setters omitted }

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:

##### package-info.java

@XmlSchema( prefix="ab", // Default namespace xmlNs={ @XmlNs(prefix="ab", namespaceURI="http://www.apache.org/addressBook/"), @XmlNs(prefix="per", namespaceURI="http://www.apache.org/person/"), @XmlNs(prefix="addr", namespaceURI="http://www.apache.org/address/"), @XmlNs(prefix="mail", namespaceURI="http://www.apache.org/mail/") } ) package org.apache.juneau.examples.addressbook;

##### Sample Code

Person person = new Person() .name("John Smith") .birthDate("1946-08-12T00:00:00Z") .addresses( new Address() .street("100 Main Street") .city("Anywhereville") .state(NY) .zip(12345) .isCurrent(true); ); // Create a new serializer with readable output, this time with namespaces enabled. // Note that this is identical to XmlSerializer.DEFAULT_NS_SQ_READABLE. XmlSerializer serializer = XmlSerializer.create().ns().ws().sq().build(); String xml = serializer.serialize(p);

Now when we run this code, we'll see namespaces added to our output:

<per:person> <per:name>John Smith</per:name> <per:birthDate>1946-08-12T04:00:00Z</per:birthDate> <per:addresses> <addr:address> <mail:street>100 Main Street</mail:street> <mail:city>Anywhereville</mail:city> <mail:state>NY</mail:state> <mail:zip>12345</mail:zip> <addr:isCurrent>true</addr:isCurrent> </addr:address> </per:addresses> </per:person>

Enabling the {@link oaj.xml.XmlSerializer#XML_addNamespaceUrisToRoot} setting results in the namespace URLs being added to the root node:

<per:person xmlns='http://www.apache.org/2013/Juneau' xmlns:per='http://www.apache.org/person/' xmlns:addr='http://www.apache.org/address/' xmlns:mail='http://www.apache.org/mail/' > <per:name>John Smith</per:name> <per:birthDate>1946-08-12T04:00:00Z</per:birthDate> <per:addresses> <addr:address> <mail:street>100 Main Street</mail:street> <mail:city>Anywhereville</mail:city> <mail:state>NY</mail:state> <mail:zip>12345</mail:zip> <addr:isCurrent>true</addr:isCurrent> </addr:address> </per:addresses> </per:person>

We can simplify the output by setting the default namespace on the serializer so that all the elements do not need to be prefixed:

// Create a new serializer with readable output, this time with namespaces enabled. XmlSerializer serializer = XmlSerializer.create().ws().sq().ns() .defaultNamespaceUri("http://www.apache.org/person/") .build();

This produces the following equivalent where the elements don't need prefixes since they're already in the default document namespace:

<person xmlns:juneau='http://www.apache.org/2013/Juneau' xmlns='http://www.apache.org/person/' xmlns:addr='http://www.apache.org/address/' xmlns:mail='http://www.apache.org/mail/' > <name>John Smith</name> <birthDate>1946-08-12T04:00:00Z</birthDate> <addresses> <addr:address> <mail:street>100 Main Street</mail:street> <mail:city>Anywhereville</mail:city> <mail:state>NY</mail:state> <mail:zip>12345</mail:zip> <addr:isCurrent>true</addr:isCurrent> </addr:address> </addresses> </person>

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.

The following code will produce the same output as before, but will perform slightly better since it avoids this pre-scan step.

// Create a new serializer with readable output, this time with namespaces enabled. XmlSerializer serializer = XmlSerializer.create() .ws() .sq() .autoDetectNamespaces(false) .namespaces("{per:'http://www.apache.org/person/'}") .build();