I have an object value
, which is of some type, either @XmlRootElement
-annotated, or not. I want to marshal it into XML:
String value1 = "test";
assertEquals("<foo>test</foo>", toXml("foo", value1));
// ...
@XmlRootElement
class Bar {
public String bar = "test";
}
assertEquals("<foo><bar>test</bar></foo>", toXml("foo", new Bar()));
Can I do it with JAXB existing facilities, or I should create some custom analyzer?
You could leverage JAXBIntrospector to do the following:
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBIntrospector;
import javax.xml.bind.Marshaller;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.namespace.QName;
public class Demo {
public static void main(String[] args) throws Exception {
Object value = "Hello World";
//Object value = new Bar();
JAXBContext jc = JAXBContext.newInstance(String.class, Bar.class);
JAXBIntrospector introspector = jc.createJAXBIntrospector();
Marshaller marshaller = jc.createMarshaller();
if(null == introspector.getElementName(value)) {
JAXBElement jaxbElement = new JAXBElement(new QName("ROOT"), Object.class, value);
marshaller.marshal(jaxbElement, System.out);
} else {
marshaller.marshal(value, System.out);
}
}
@XmlRootElement
public static class Bar {
}
}
With the above code when the JAXBElement is marshalled it will be qualified with an xsi:type attribute corresponding to the appropriate schema type:
<ROOT
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xs="http://www.w3.org/2001/XMLSchema" xsi:type="xs:string">Hello World</ROOT>
To eliminate the qualification you can simply change the line that creates the JAXBElement to:
JAXBElement jaxbElement = new JAXBElement(new QName("ROOT"), value.getClass(), value);
This will result in the following XML:
<ROOT>Hello World</ROOT>
Here is how to marshal value1
, which is a String
. You can pass yourObject.getClass()
to the JAXBElement
constructor, and value1
:
try {
JAXBContext jc = JAXBContext.newInstance();
Marshaller m = jc.createMarshaller();
String value1 = "test";
JAXBElement jx = new JAXBElement(new QName("foo"), value1.getClass(), value1);
m.marshal(jx, System.out);
} catch (JAXBException ex) {
ex.printStackTrace();
}
This works without using @XmlRootElement
. The result of the code above was:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><foo>test</foo>
On the other part, this will not work with a Bar
object: javax.xml.bind.JAXBException: myPackage.Bar is not known to this context
. However, you can get the value from inside Bar
, and create the JAXBElement
with that, not the object itself.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With