Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jaxb complex xml unmarshall

Tags:

java

jaxb

I am having issues to unmarshall nested xml below. Can someone please advise if I am missing something.
body tag can contain any Jaxb anotated obj.
Do I have to create a custom adapter for marshalling/unmarshalling such xml?

Input XML

<?xml version="1.0" encoding="UTF-8"?>
<serviceRq xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="serviceRq">
  <body>   
    <createRq>
       <id>1234</id>
    </createRq>
  </body>
</serviceRq>

My Jaxb-annotated classes are:

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "serviceRq")
public class ServiceRq{    
    private Object body;
    <!-- getters and setters omitted-->
}

Here, body can be any jaxb annotated object, in this case its CreateRq.

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "createRq")
public class CreateRq{    
    private String id;
    <!-- getters and setters omitted-->
}

I am looking for a generic way to support any Jaxb annotated object in body of the input xml.

like image 394
BSingh Avatar asked May 16 '11 16:05

BSingh


People also ask

How does JAXB read XML?

To read XML, first get the JAXBContext . It is entry point to the JAXB API and provides methods to unmarshal, marshal and validate operations. Now get the Unmarshaller instance from JAXBContext . It's unmarshal() method unmarshal XML data from the specified XML and return the resulting content tree.

Does JAXB use DOM or SAX?

JAXB allows applications to access the data in the XML from the object rather than using the DOM or SAX to retrieve the data from a direct representation of the XML itself. It is most often used alongside Java API for XML Web Services (JAX-WS) and makes objects creation and mapping easy.


1 Answers

You could use a @XmlAnyElement(lax=true) and an XmlAdapter to handle this use case:

ServiceRq

import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "serviceRq")
public class ServiceRq{    

    @XmlJavaTypeAdapter(value=BodyAdapter.class)
    private Object body;
    // getters and setters omitted
}

BodyAdapter

import javax.xml.bind.annotation.adapters.XmlAdapter;

public class BodyAdapter extends XmlAdapter<Body, Object>{

    @Override
    public Object unmarshal(Body v) throws Exception {
        return v.getValue();
    }

    @Override
    public Body marshal(Object v) throws Exception {
        Body body = new Body();
        body.setValue(v);
        return body;
    }

}

Body

import javax.xml.bind.annotation.XmlAnyElement;

public class Body {

    private Object value;

    @XmlAnyElement(lax=true)
    public Object getValue() {
        return value;
    }

    public void setValue(Object value) {
        this.value = value;
    }

}

CreateRq

import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "createRq")
public class CreateRq{    
    private String id;
    // getters and setters omitted
}

Demo

import java.io.File;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(ServiceRq.class);
        System.out.println(jc);

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        ServiceRq serviceRq = (ServiceRq) unmarshaller.unmarshal(new File("input.xml"));

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(serviceRq, System.out);

    }

}

For More Information

  • http://bdoughan.blogspot.com/2010/08/using-xmlanyelement-to-build-generic.html
  • http://bdoughan.blogspot.com/2010/07/xmladapter-jaxbs-secret-weapon.html
  • http://bdoughan.blogspot.com/2010/12/jaxb-and-immutable-objects.html
  • http://bdoughan.blogspot.com/2010/12/represent-string-values-as-element.html
like image 127
bdoughan Avatar answered Sep 28 '22 01:09

bdoughan