2

I have a class A with attributes B b and C c that I want to marshall and unmarshall in a way that in c instead of having an java object graph, I want a string representation of the XML fragment, i.e.

@XmlRootElement(namespace="test")
public class A {
   B b;
   C c;
   //omitting getters and setters
}

public class C {
   String xmlFragment;
   //This string will contain the following:
   //"<d>d</d><e><f>f1</f><f>f2</></e>
}

and the resulting/producing XML will look like

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<A xmlns="test">
 <B>some B content that is mapped to java objects</B>
 <C>
   <d>d</d><e><f>f1</f><f>f2</></e>
 </C>
</A>

How could I accomplish that using JAXB?

ilcavero
  • 3,012
  • 1
  • 31
  • 27

2 Answers2

3

JAXB won't quite do that. What it can do is handle a org.w3c.dom.Element, and serialize that as XML, i.e.

@XmlRootElement(namespace="test")
public class A {
   B b;
   @XmlAnyElement Element c;
}

So you need to parse that XML fragment into an Element (e.g. using DocumentBuilderFactory), and then it'll work.

You could, I suppose, parse the Element at runtime, but be very careful of the performance hit:

@XmlRootElement(namespace="test")
public class A {
   B b;
   String xmlFragment;

   @XmlAnyElement
   public Element getXmlFragment() {
       InputSource source = new InputSource(new StringReader(xmlFragment));
       Document doc = DocumentBuilderFactory.newInstance().parse(source);
       return doc.getDocumentElement();
   }
}
skaffman
  • 398,947
  • 96
  • 818
  • 769
  • I couldn't make "Element c" work because JAXB complains that it doesn't work on interfaces, now if I leave it as Object, I can parse it later on and it works. is that the right way to do it? – ilcavero Jul 20 '11 at 12:32
  • @ilcavero: Oops, my mistake, forgot to add `@XmlAnyElement`. See edited answer. – skaffman Jul 20 '11 at 12:35
1

You'll need to use an XmlAdapter implementation for type C.

@XmlRootElement(namespace="test")
public class A {
   B b;
   @XmlJavaTypeAdapter(MyAdapter.class)
   C c;
    //omitting getters and setters
} 

class MyAdapter extends XmlAdapter<String,C> {
   public C unmarshal(String s) {
      // custom unmarshalling
      return null;
   }
   public String marshal(C c) {
      // custom marshalling
      return "blah";
   }
}

Hope this is what you're after.

Regards Yusuf

Yusuf Jakoet
  • 136
  • 3
  • thanks for your answer, is not really what I'm looking for because I would have to build the XML by hand using the getters of C on "String marshal(C c)", when what I want is the XML used by the marshaller to create the c object that then was passed to the XMLAdapter. What I'm looking for is something closer to the use of @XMLAnyElement where you get a DOM model of the XML, which I could easily turn into String http://jaxb.java.net/tutorial/section_6_2_7_6-Collecting-Unspecified-Elements-XmlAnyElement.html – ilcavero Jul 18 '11 at 12:00