Reputation: 2820
I want to avoid adding an annotation @XMLRootElement to every POJO that I will used to unmarshall a xml. Is there a way to set or add programmatically XmlRootElement to a class?
//@XmlRootElement here
public class Person{
private String name;
private String address;
//other fields
//getters and setters here
If not possible, how can I unmarshall a xml without XmlRootElement in POJO?
public static <T> T unmarshal(Class clazz, String xml) {
try {
JAXBContext ctx = JAXBContext.newInstance(clazz);
Unmarshaller u = ctx.createUnmarshaller();
return (T) u.unmarshal(new StringReader(xml));
} catch (JAXBException e) {
throw new RuntimeException("Error interpreting XML response", e);
}
}
Exception thrown without @XmlRootElement:
Caused by: javax.xml.bind.UnmarshalException: unexpected element (uri:"", local:"report"). Expected elements are (none)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.handleEvent(UnmarshallingContext.java:556)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader.reportError(Loader.java:199)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader.reportError(Loader.java:194)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader.reportUnexpectedChildElement(Loader.java:71)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext$DefaultRootLoader.childElement(UnmarshallingContext.java:962)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext._startElement(UnmarshallingContext.java:399)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.startElement(UnmarshallingContext.java:380)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.SAXConnector.startElement(SAXConnector.java:101)
at org.apache.xerces.parsers.AbstractSAXParser.startElement(Unknown Source)
at org.apache.xerces.impl.XMLNSDocumentScannerImpl.scanStartElement(Unknown Source)
at org.apache.xerces.impl.XMLNSDocumentScannerImpl$NSContentDispatcher.scanRootElementHook(Unknown Source)
at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl$FragmentContentDispatcher.dispatch(Unknown Source)
at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source)
at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
at org.apache.xerces.parsers.XMLParser.parse(Unknown Source)
at org.apache.xerces.parsers.AbstractSAXParser.parse(Unknown Source)
at org.apache.xerces.jaxp.SAXParserImpl$JAXPSAXParser.parse(Unknown Source)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:195)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:168)
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:137)
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:194)
EDITED:
Blaise answer was actually working.
StreamSource source = new StreamSource(new StringReqder(xml));
return (T) u.unmarshal(source, clazz).getValue();
but when I'm trying to used it to return a List
//this works when I specify @XmlRootElement
private static <T> List<T> unmarshallCollection(Class<T> clazz, Source source)
throws JAXBException {
JAXBContext ctx = JAXBContext.newInstance(WrapperCollection.class, clazz);
Unmarshaller u = ctx.createUnmarshaller();
WrapperCollection<T> collection = u.unmarshal(source, WrapperCollection.class).getValue();
return collection.getItems();
}
and it throws an exception cannot org.apache.xerces.dom.ElementNSImpl cannot be cast to .. What did I do wrong?
Upvotes: 1
Views: 2540
Reputation: 149047
You just need to use one of the unmarshal
methods that take a Class
parameter.
StreamSource source = new StreamSource(new StringReqder(xml));
return (T) u.unmarshal(source, clazz).getValue();
Note
JAXBElement
this holds the root element information you can get the unmarshalled object by calling getValue
on it.JAXBElement
and then marshal that.Upvotes: 3