Team lead for the TopLink/EclipseLink JAXB & SDO implementations, and the Oracle representative on those specifications. Blaise is a DZone MVB and is not an employee of DZone and has posted 44 posts at DZone. You can read more from them at their website. View Full User Profile

JAXB and Namespace Prefixes

12.03.2011
| 26430 views |
  • submit to reddit

In a previous post I covered how to use namespace qualification with JAXB.  In this post I will cover how to control the prefixes that are used.  This is not covered in the JAXB (JSR-222) specification but I will demonstrate the extensions available in both the reference and EclipseLink MOXy implementations for handling this use case

Java Model

The following domain model will be used for this post.  The @XmlRootElement and @XmlElement annotation are used to specify the appropriate namespace qualification.

package blog.prefix;
 
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
 
@XmlRootElement(namespace="http://www.example.com/FOO")
public class Root {
 
    private String a;
    private String b;
    private String c;
 
    @XmlElement(namespace="http://www.example.com/BAR")
    public String getA() {
        return a;
    }
 
    public void setA(String a) {
        this.a = a;
    }
 
    @XmlElement(namespace="http://www.example.com/FOO")
    public String getB() {
        return b;
    }
 
    public void setB(String b) {
        this.b = b;
    }
 
    @XmlElement(namespace="http://www.example.com/OTHER")
    public String getC() {
        return c;
    }
 
    public void setC(String c) {
        this.c = c;
    }
 
}

Demo Code

We will use the following code to populate the domain model and produce the XML.

package blog.prefix;
 
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
 
public class Demo {
 
    public static void main(String[] args) throws Exception {
        JAXBContext ctx = JAXBContext.newInstance(Root.class);
 
        Root root = new Root();
        root.setA("A");
        root.setB("B");
        root.setC("OTHER");
 
        Marshaller m = ctx.createMarshaller();
        m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        m.marshal(root, System.out);
    }
 
}

 

Output

XML like the following is produced by default.  The JAXB implementation has arbitrarily assigned prefixes to the namespace URIs specified in the domain model:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns2:root
    xmlns="http://www.example.com/BAR"
    xmlns:ns2="http://www.example.com/FOO"
    xmlns:ns3="http://www.example.com/OTHER">
    <a>A</a>
    <ns2:b>B</ns2:b>
    <ns3:c>OTHER</ns3:c>
</ns2:root>

Specify Prefix Mappings with JAXB RI & Metro JAXB

The reference and Metro implementations of JAXB provide a mechanism called NamespacePrefixMapper to control the prefixes that will be assigned to namespaces.

NamespacePrefixMapper

package blog.prefix;
 
import com.sun.xml.internal.bind.marshaller.NamespacePrefixMapper;
//import com.sun.xml.bind.marshaller.NamespacePrefixMapper;
 
public class MyNamespaceMapper extends NamespacePrefixMapper {
 
    private static final String FOO_PREFIX = ""; // DEFAULT NAMESPACE
    private static final String FOO_URI = "http://www.example.com/FOO";
 
    private static final String BAR_PREFIX = "bar";
    private static final String BAR_URI = "http://www.example.com/BAR";
 
    @Override
    public String getPreferredPrefix(String namespaceUri, String suggestion, boolean requirePrefix) {
        if(FOO_URI.equals(namespaceUri)) {
            return FOO_PREFIX;
        } else if(BAR_URI.equals(namespaceUri)) {
            return BAR_PREFIX;
        }
        return suggestion;
    }
 
    @Override
    public String[] getPreDeclaredNamespaceUris() {
        return new String[] { FOO_URI, BAR_URI };
    }
 
}

Demo Code

The NamespacePrefixMapper is set on an instance of Marshaller. I would recommend wrapping the setPropery call in a try/catch block so that your application does not fail if you change JAXB implementations.

package blog.prefix;
 
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
 
public class Demo {
 
    public static void main(String[] args) throws Exception {
        JAXBContext ctx = JAXBContext.newInstance(Root.class);
 
        Root root = new Root();
        root.setA("A");
        root.setB("B");
        root.setC("OTHER");
 
        Marshaller m = ctx.createMarshaller();
        m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        try {
            m.setProperty("com.sun.xml.internal.bind.namespacePrefixMapper", new MyNamespaceMapper());
            //m.setProperty("com.sun.xml.bind.namespacePrefixMapper", new MyNamespaceMapper());
        } catch(PropertyException e) {
            // In case another JAXB implementation is used
        }
        m.marshal(root, System.out);
    }
 }

Output

The resulting document now uses the NamespacePrefixMapper to determine the prefixes that should be used in the resulting document.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<root
    xmlns:bar="http://www.example.com/BAR"
    xmlns="http://www.example.com/FOO"
    xmlns:ns3="http://www.example.com/OTHER">
    <bar:a>A</bar:a>
    <b>B</b>
    <ns3:c>OTHER</ns3:c>
</root>

 

Specify Prefix Mappings with EclipseLink JAXB (MOXy)

MOXy will use the namespace prefixes as they are defined on the @XmlSchema annotation.  In order for MOXy to be able to use the default namespace the elementFormDefault property on the @XmlSchema annotation must be set to XmlNsForm.QUALIFIED.

package-info

XmlSchema(
    elementFormDefault=XmlNsForm.QUALIFIED,
    namespace="http://www.example.com/FOO",
    xmlns={@XmlNs(prefix="bar",
                  namespaceURI="http://www.example.com/BAR")}
)
package blog.prefix;
 
import javax.xml.bind.annotation.XmlNs;
import javax.xml.bind.annotation.XmlNsForm;
import javax.xml.bind.annotation.XmlSchema;

Output

The resulting document now uses the xmlns setting from the @XmlSchema annotation to determine the prefixes that should be used in the resulting document.

<?xml version="1.0" encoding="UTF-8"?>
<root
   xmlns="http://www.example.com/FOO"
   xmlns:ns0="http://www.example.com/OTHER"
   xmlns:bar="http://www.example.com/BAR">
   <bar:a>A</bar:a>
   <b>B</b>
   <ns0:c>OTHER</ns0:c>
</root>

Further Reading

If you enjoyed this post then you may also be interested in:

 

 

From http://blog.bdoughan.com/2011/11/jaxb-and-namespace-prefixes.html

Published at DZone with permission of Blaise Doughan, author and DZone MVB.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Tags:

Comments

John David replied on Wed, 2012/01/25 - 7:06pm

The XML and Java technology are natural partners in helping developers exchange data and programs across the Internet. That's because XML has emerged as the standard for exchanging data across disparate systems, and Java technology provides a platform for building portable applications. This partnership is particularly important for Web services, which promise users and application developers program functionality on demand from anywhere to anywhere on the Web. XML and Java technology are recognized as ideal building blocks for developing Web services and applications that access Web services.

new java

Sangeetha Jayaraman replied on Wed, 2013/09/11 - 5:29am

I am new to jaxb, please help me  to parse below xml

<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Invoice xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:schemas-basda-org:2000:salesInvoice:xdr:3.01">    <InvoiceHead>        <Schema>            <Version>3</Version>        </Schema>    </InvoiceHead>    <Extensions>        <dps:InvoiceExtensions xmlns:dps="urn:eBIS:DPS:Extension:1.0">            <dps:DocumentID>Sri</dps:DocumentID>        </dps:InvoiceExtensions>    </Extensions>

</Invoice>

I can easily parse the  InvoiceHead tag but i am unable to parse the extensions tag can you pls help me how to parse the extensions tag with prefix  like <<dps:InvoiceExtensions>

<Extensions>        <dps:InvoiceExtensions xmlns:dps="urn:eBIS:DPS:Extension:1.0">            <dps:DocumentID>Sri</dps:DocumentID>        </dps:InvoiceExtensions>    </Extensions>


Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.