JAXB: how to append sub-tree to an object and create a full tree

vlsuabniplm

New Member
I have one sub-tree that I would like to append set on an object and make JAXB marshall the all thing as a single tree (and with appropriate tags). But currently, the root tag of the sub-tree is replaced by the tag of other objectUnfortunately, I am not allow to publish the original code here, so I reproduced my problem in a test code (so bear with me if you find this dumb).The idea is that I would like to output the following structure:\[code\]<?xml version="1.0" encoding="UTF-8" standalone="yes"?><ns2:Root xmlns:ns2="urn:my:foo:bar:1.0" xmlns:ns3="urn:other:foo:bar:1.1"> <Content> <Header> <ns3:Leaf/> </Header> </Content></ns2:Root>\[/code\]but currently, all I get is this:\[code\]<?xml version="1.0" encoding="UTF-8" standalone="yes"?><ns2:Root xmlns:ns2="urn:my:foo:bar:1.0" xmlns:ns3="urn:other:foo:bar:1.1"> <Content> <Header/> </Content></ns2:Root>\[/code\]I have two XSD's to generate all the necessary classes, so I am ok on that side (but since those classes are generated, I cannot modify them).Here is a sample code that produces the second XML (the wrong one):\[code\]package foo.bar;import java.io.OutputStream;import javax.xml.bind.JAXBContext;import javax.xml.bind.JAXBException;import javax.xml.bind.Marshaller;import javax.xml.bind.annotation.XmlAccessType;import javax.xml.bind.annotation.XmlAccessorType;import javax.xml.bind.annotation.XmlElement;import javax.xml.bind.annotation.XmlRootElement;import javax.xml.bind.annotation.XmlType;import javax.xml.parsers.DocumentBuilder;import javax.xml.parsers.DocumentBuilderFactory;import javax.xml.parsers.ParserConfigurationException;import org.w3c.dom.Document;import org.w3c.dom.Node;public class Test { private JAXBContext context; public Test() throws JAXBException { context = JAXBContext.newInstance(RootElement.class, LeafElement.class); } @XmlRootElement(name = "Root", namespace = "urn:my:foo:bar:1.0") @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "Root", propOrder = { "content" }) public static class RootElement { @XmlElement(name = "Content") protected ContentElement content; public ContentElement getContent() { return content; } public void setContent(ContentElement content) { this.content = content; } } @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "Content", propOrder = { "dummy" }) public static class ContentElement { @XmlElement(name = "Header") protected Object dummy; public Object getDummy() { return dummy; } public void setDummy(Object dummy) { this.dummy = dummy; } } @XmlRootElement(name = "Leaf", namespace = "urn:other:foo:bar:1.1") @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "Leaf") public static class LeafElement { } public Node marshal(Object obj) throws JAXBException { DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setNamespaceAware(true); Document doc = null; try { DocumentBuilder db = dbf.newDocumentBuilder(); doc = db.newDocument(); } catch (ParserConfigurationException ex) { throw new JAXBException(ex); } Marshaller m = context.createMarshaller(); m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); m.marshal(obj, doc); return doc.getDocumentElement(); } public void marshal(Object obj, OutputStream stream) throws JAXBException { Marshaller m = context.createMarshaller(); m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); m.marshal(obj, stream); } public void test() throws JAXBException { RootElement root = new RootElement(); ContentElement content = new ContentElement(); root.setContent(content); LeafElement leaf = new LeafElement(); content.setDummy(marshal(leaf)); marshal(root, System.out); } public static void main(String[] args) throws JAXBException { new Test().test(); }}\[/code\]In that code you find 3 "marshallable" classes: \[code\]RootElement\[/code\], \[code\]ContentElement\[/code\] and \[code\]LeafElement\[/code\]. The first two classes come from one XSD (with a given namespace) and the last one comes from another XSD (with another namespace), as illustrated in the sample code.So far, all I found to fix this, was to create an additional class that would be set as \[code\]dummy\[/code\] on the ContentElement and would itself hold the LeafElement, so that JAXB creates the appropriate intermdiate Node. But I find this solution quite ugly, not really maintainable and was hoping that JAXB had some way to handle such cases.If you need more info, or you need me to re-formulate my question, don't hesitate. I am having a hard time to explain my problem with simple words.Constraints are the following:
  • I cannot modify RootElement, ContentElement nor LeafElement
  • I cannot use something else than JAXB
 
Back
Top