Reputation: 8116
I have been provided with an xsd that I compiled to Java classes using JAXB.
The generated classes create an abstract class called "Event" and several classes that extend it.
e.g. "DerivedEvent"
I am using the following to marshal it to XML.
ObjectFactory objectFactory = new ObjectFactory();
DerivedEvent derivedEvent = objectFactory.createDerivedEvent();
JAXBContext context = JAXBContextImpl.newInstance("com.my.root.namespace");
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
marshaller.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);
Class partialClass = Event.class;
QName partNamespace = new QName(Event.class.getSimpleName());
Object element = new JAXBElement(partNamespace, partialClass, derivedEvent);
// Create a stringWriter to hold the XML
StringWriter stringWriter = new StringWriter();
marshaller.marshal(element, stringWriter);
String xml = stringWriter.toString();
This then outputs the wrong root element. i.e.
<Event xsi:type="DerivedEvent" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<DerivedStartPeriod xsi:nil="true"/>
<DerivedEndPeriod xsi:nil="true"/>
</Event>
instead of
<DerivedEvent>
<DerivedStartPeriod xsi:nil="true" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>
<DerivedEndPeriod xsi:nil="true" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>
</DerivedEvent>
If I set the partialClass and partNamespace to DerivedEvent it outputs the correct information. However, I can't really do that as this marshalling is in a flow where the event could be one of 50 different derived events.
I can't really change the xsd to have substitution groups as mentioned here http://blog.bdoughan.com/2010/11/jaxb-and-inheritance-using-substitution.html as this change is likely to be lost when I am provided with a new version of the xsd.
I need to use the partial class and namespace as the Events are not root elements.
Can I add the events to be XmlRootElements with bindings somehow?
Or is there another way to address this?
Upvotes: 1
Views: 1792
Reputation: 523
Creating a JAXBElement through generated ObjectFactory
, or use proper QName.
This is bad:
QName partNamespace = new QName(Event.class.getSimpleName());
It should be like this
QName partNamespace = new QName("your namespace", "DerivedEvent");
You should find qname like this in ObjectFactory
probably as constant...
ObjectFactory
probably contains method createDerivedEvent
with one argument of type DerivedEvent. It returns JAXBElement which can be marshaled to xml.
Upvotes: 1
Reputation: 8116
I eventually found this page that helped me add the XmlRootElement:
https://codereview.stackexchange.com/questions/1877/jaxb-xjc-code-generation-adding-xmlrootelement-and-joda-datetime
Which I got working (dependencies/build.xml etc) by using the Annotate sample here:
http://confluence.highsource.org/display/J2B/Home
Upvotes: 1