JAXB unmarshal object in multiple packages with different namespace

Our situation is we receive some xml from web service without namespace, but the model(the the previous version of this Web service) in our code requires namespace.

Directly unmarshall the xml will result in null for the underlying objects. So we have to find a way to inject the namespace. To do this, we need a SAX xml reader so that before giving the xml to the unmarshaller, we could to our tweaking in SAX(add namespace).

To achieve this, we need to create a XML reader which reads the xml and then set a filter for the reader to add namespace

public class MyNamespaceFilter extends XMLFilterImpl
{
    private String regulatorNamespaceUri;
    private String subscriptionNamespaceUri;
    private boolean addNamespace;

    private boolean addedNamespace = false;
    private HashSet<String> subscriptionElements = new HashSet<String>();

    
    public MyNamespaceFilter(String namespaceUri, String subscriptionUri, boolean addNamespace)
    {
        super();

        if (addNamespace)
        {
            this.regulatorNamespaceUri = namespaceUri;
            this.subscriptionNamespaceUri = subscriptionUri;
        }
        else
        {
            this.regulatorNamespaceUri = "";
        }
        this.addNamespace = addNamespace;

        //add subscription Uris since they use different name space.
        subscriptionElements.add("Issue");
        subscriptionElements.add("UnderlyingSecurities");
        subscriptionElements.add("Security");
    }


    @Override
    public void startDocument() throws SAXException
    {
        super.startDocument();
        if (addNamespace)
        {
            startControlledPrefixMapping();
        }
    }


    @Override
    public void startElement(String arg0, String arg1, String arg2, Attributes arg3) throws SAXException
    {
        String uriToBeUsed = this.regulatorNamespaceUri;
        if (subscriptionElements.contains(arg1))
        {
            uriToBeUsed = subscriptionNamespaceUri;
        }
        super.startElement(uriToBeUsed, arg1, arg2, arg3);
    }

    @Override
    public void endElement(String arg0, String arg1, String arg2) throws SAXException
    {

        super.endElement(this.regulatorNamespaceUri, arg1, arg2);
    }

    @Override
    public void startPrefixMapping(String prefix, String url) throws SAXException
    {
        if (addNamespace)
        {
            this.startControlledPrefixMapping();
        }

    }

    private void startControlledPrefixMapping() throws SAXException
    {
        if (this.addNamespace && !this.addedNamespace)
        {
            //We should add namespace since it is set and has not yet been done.
            super.startPrefixMapping("", this.regulatorNamespaceUri);

            //Make sure we dont do it twice
            this.addedNamespace = true;
        }
    }

}


Then we could use it in the code:

//Prepare JAXB objects
JAXBContext jc = JAXBContext.newInstance("jaxb.package");
Unmarshaller u = jc.createUnmarshaller();

//Create an XMLReader to use with our filter
XMLReader reader = XMLReaderFactory.createXMLReader();

//Create the filter (to add namespace) and set the xmlReader as its parent.
MyNamespaceFilter inFilter = new MyNamespaceFilter("http://www.example.com/namespaceurl", true);
inFilter.setParent(reader);

//Prepare the input, in this case a java.io.File (output)
InputSource is = new InputSource(new FileInputStream(output));

//Create a SAXSource specifying the filter
SAXSource source = new SAXSource(inFilter, is);

//Do unmarshalling
Object myJaxbObject = u.unmarshal(source);

More details HERE

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s