Namespaces
Let's go back to the example of our original Person bean class, but add some namespace annotations:
@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:
@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;
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();