The annotation on Brochure.courses says that you want to have a
sub-element <course>. Note that nothing here indicates that this
element would have - expressed in XML Schema language -
maxOccurs="unbounded". So there is going to be a single <course>
element. The Course[] that's going to be used for the contents
of <course> needs some intermediary level for separating its
elements - that's why you have the <item>s. In short: I don't think
you're doing anything wrong.
If you do want an XML structure without the additional XML level,
you'll have to let JAXB see a collection, to be marshalled as
Brochure's sub-element, e.g.:
@XmlElement(name="courses")
Collection<Course> courses;
Another option would be to adapt Brochure (and not its field). This
doesn't work for Brochure being a root element, but given this
additional class
@XmlRootElement(name="college")
public class College {
@XmlElement
public Brochure brochure;
public College(){}
public College( Brochure b ){
brochure = b;
}
}
you can write Brochure.java as
@XmlJavaTypeAdapter(BrochureAdapter.class)
public class Brochure {
Map<String,Course> courses;
public Brochure() {
courses = new HashMap<String, Course>();
}
}
BrochureAdapter.java maps a Brochure to a class Courses which informs
JAXB about the desired XML structure:
public class Courses {
@XmlElement(name="course")
public Course[] carray;
}
public class BrochureAdapter
extends XmlAdapter<Courses,Brochure> {
public Brochure unmarshal( Courses value ) {
Brochure b = new Brochure();
for( Course c : value.carray )
b.courses.put( c.id, c );
return b;
}
public Courses marshal( Brochure b ) {
Courses courses = new Courses();
Collection<Course> c = b.courses.values();
courses.carray = c.toArray(new Course[c.size()]);
return courses;
}
}
And this is what you'll get now
<college>
<brochure>
<course id="c1">
<name>Course 1</name>
</course>
<course id="c0">
<name>Course 0</name>
</course>
</brochure>
</college>
HTH,
Wolfgang
On Sun, Aug 24, 2008 at 4:39 AM, murakris <cme_mk_at_yahoo.com> wrote:
>
> Hi, I'm trying to follow the XmlAdapter example in Koshuke's blog here:
> http://weblogs.java.net/blog/kohsuke/archive/2005/04/xmladapter_in_j.html
>
> and when I try to marshall the Brochure class, it results in xml output like
> this:
> <brochure>
> <course>
> <item id="c0">
> <name>Course 0</name>
> </item>
> <item id="c1">
> <name>Course 1</name>
> </item>
> </course>
> </brochure>
>
> instead of
> <brochure>
> <course id="c0">
> <name>Course 0</name>
> </item>
> <course id="c1">
> <name>Course 1</name>
> </item>
> </brochure>
>
> Can you please help me understand what I'm doing wrong? Below is the rest of
> the code:
>
> Brochure.java:
> @XmlRootElement(name="brochure")
> public class Brochure {
> @XmlJavaTypeAdapter(CourseListAdapter.class)
> @XmlElement(name="course")
> Map<String,Course> courses;
>
> public Brochure() {
> courses = new HashMap<String, Course>();
> }
> }
>
> Course.java
> public class Course {
> @XmlAttribute
> String id;
> @XmlElement
> String name;
> }
>
> CourseListAdapter
> public class CourseListAdapter extends XmlAdapter<Course[],
> Map<String,Course>> {
> public Map<String,Course> unmarshal( Course[] value ) {
> Map<String,Course> r = new HashMap<String,Course>();
> for( Course c : value )
> r.put(c.id,c);
> return r;
> }
> public Course[] marshal( Map<String,Course> value ) {
> return value.values().toArray(new Course[value.size()]);
> }
>
> Test class:
> public class Main {
>
> @Test public void test() throws Exception {
> JAXBContext jc = JAXBContext.newInstance(Brochure.class);
> Marshaller m = jc.createMarshaller();
> m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
>
> Brochure b = new Brochure();
> for (int i=0; i<2; i++) {
> Course c = getCourse(i);
> b.courses.put(c.id, c);
> }
>
> m.marshal(b, System.out);
>
> }
>
> public Course getCourse(int i) {
> Course c1 = new Course();
> c1.id="c" + i;
> c1.name="Course " + i;
> return c1;
> }
> }
>
> }
>
> Thanks in advance!
> Murali