Skip to main content

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 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 @Xml annotation, or can be defined at the package level with the @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 XmlSerializer.XML_addNamespaceUrisToRootsetting 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/")

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>

By default, the XML serializer class will 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 using XmlSerializer.Builder.disableAutoDetectNamespaces().

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();