tags:

views:

643

answers:

1

From http://weblogs.java.net/blog/2005/04/22/xmladapter-jaxb-ri-ea

import java.io.StringReader;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.Map;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;

public class BrochureOriginal {
  @XmlRootElement(name = "brochure")
  static class Brochure {
    @XmlJavaTypeAdapter(CourseListAdapter.class)
    @XmlElement(name = "courses")
    Map<String, Course> coursesByIdMap;
  }

  static class Course {
    @XmlAttribute
    String id;

    @XmlElement
    String name;

  }

  static class CourseListAdapter extends XmlAdapter<Course[], Map<String, Course>> {
    public Course[] marshal(Map<String, Course> value) {
      return value.values().toArray(new Course[value.size()]);
    }

    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;
    }

  }

  private static <T> String convertObjectToXml(Class<T> clazz, T instance) {
    try {
      JAXBContext jc = JAXBContext.newInstance(clazz);
      Marshaller m = jc.createMarshaller();
      m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
      StringWriter sw = new StringWriter();
      m.marshal(instance, sw);
      return sw.toString();
    } catch (Exception e) {
      e.printStackTrace();
      return null;
    }
  }

  @SuppressWarnings("unchecked")
  private static <T> T convertXmlToObject(Class<T> clazz, String xml) {
    try {
      JAXBContext jc = JAXBContext.newInstance(clazz);
      Unmarshaller m = jc.createUnmarshaller();
      StringReader sr = new StringReader(xml);
      T instance = (T) m.unmarshal(sr);
      return instance;
    } catch (Exception e) {
      e.printStackTrace();
      return null;
    }
  }

  public static void main(String[] args) {

    Brochure b = new Brochure();
    Course c = null;

    // 1st course
    c = new Course();
    c.id = "cs501";
    c.name = "Software Engineering";
    b.coursesByIdMap = new HashMap<String, Course>();
    b.coursesByIdMap.put(c.id, c);

    // 2nd course
    c = new Course();
    c.id = "cs519";
    c.name = "Network Security";
    b.coursesByIdMap.put(c.id, c);

    Brochure source = b;
    String sourceDisplay = getDisplay(source);
    String xml = convertObjectToXml(Brochure.class, b);
    System.out.println(sourceDisplay);
    System.out.println(xml);

    Brochure restored = convertXmlToObject(Brochure.class, xml);
    String restoredDisplay = getDisplay(restored);
    System.out.println(restoredDisplay);

  }

  private static String getDisplay(Brochure b) {
    String nl = System.getProperty("line.separator");
    StringBuilder sb = new StringBuilder();
    sb.append(nl + "Brochure");
    for (Map.Entry<String, Course> entry : b.coursesByIdMap.entrySet()) {
      Course course = entry.getValue();
      sb.append(nl + "  coursesByIdMap.entry");
      sb.append(nl + "    key:   String(" + entry.getKey() + ")");
      sb.append(nl + "    value: Course(id=" + course.id + ", name=" + course.name + ")");
    }
    return sb.toString();
  }

}

This is the output...

Brochure
  coursesByIdMap.entry
    key:   String(cs519)
    value: Course(id=cs519, name=Network Security)
  coursesByIdMap.entry
    key:   String(cs501)
    value: Course(id=cs501, name=Software Engineering)
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<brochure>
    <courses>
        <item id="cs519">
            <name>Network Security</name>
        </item>
        <item id="cs501">
            <name>Software Engineering</name>
        </item>
    </courses>
</brochure>


Brochure
  coursesByIdMap.entry
    key:   String(cs519)
    value: Course(id=cs519, name=Network Security)
  coursesByIdMap.entry
    key:   String(cs501)
    value: Course(id=cs501, name=Software Engineering)

I was wanting something like...

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<brochure>
    <courses>
        <course id="cs519">
            <name>Network Security</name>
        </course>
        <course id="cs501">
            <name>Software Engineering</name>
        </course>
    </courses>
</brochure>

I can't seem to find a way to get rid of that "item" element name.

From the resources of the answer, here is a way to do it with a crutch object.

import java.io.StringReader;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.Map;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;

public class BrochureTest {
  @XmlRootElement(name = "brochure")
  static class Brochure {
    @XmlJavaTypeAdapter(CourseListAdapter.class)
    @XmlElement(name = "courses")
    Map<String, Course> coursesByIdMap;
  }

  static class Course {
    @XmlAttribute
    String id;

    @XmlElement
    String name;

  }

  static class CourseListAdapter extends XmlAdapter<CoursesJaxbCrutch, Map<String, Course>> {
    public CoursesJaxbCrutch marshal(Map<String, Course> value) {
      CoursesJaxbCrutch courses = new CoursesJaxbCrutch();
      courses.courses = value.values().toArray(new Course[value.size()]);
      return courses;
    }

    public Map<String, Course> unmarshal(CoursesJaxbCrutch value) {
      Map<String, Course> r = new HashMap<String, Course>();
      for (Course c : value.courses)
        r.put(c.id, c);
      return r;
    }

  }

  private static class CoursesJaxbCrutch {
    @XmlElement(name = "course")
    private Course[] courses;
  }

  private static <T> String convertObjectToXml(Class<T> clazz, T instance) {
    try {
      JAXBContext jc = JAXBContext.newInstance(clazz);
      Marshaller m = jc.createMarshaller();
      m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
      StringWriter sw = new StringWriter();
      m.marshal(instance, sw);
      return sw.toString();
    } catch (Exception e) {
      e.printStackTrace();
      return null;
    }
  }

  @SuppressWarnings("unchecked")
  private static <T> T convertXmlToObject(Class<T> clazz, String xml) {
    try {
      JAXBContext jc = JAXBContext.newInstance(clazz);
      Unmarshaller m = jc.createUnmarshaller();
      StringReader sr = new StringReader(xml);
      T instance = (T) m.unmarshal(sr);
      return instance;
    } catch (Exception e) {
      e.printStackTrace();
      return null;
    }
  }

  public static void main(String[] args) {

      Brochure b = new Brochure();
    Course c = null;

    // 1st course
    c = new Course();
    c.id = "cs501";
    c.name = "Software Engineering";
    b.coursesByIdMap = new HashMap<String, Course>();
    b.coursesByIdMap.put(c.id, c);

    // 2nd course
    c = new Course();
    c.id = "cs519";
    c.name = "Network Security";
    b.coursesByIdMap.put(c.id, c);

    Brochure source = b;
    String sourceDisplay = getDisplay(source);
    String xml = convertObjectToXml(Brochure.class, b);
    System.out.println(sourceDisplay);
    System.out.println(xml);

    Brochure restored = convertXmlToObject(Brochure.class, xml);
    String restoredDisplay = getDisplay(restored);
    System.out.println(restoredDisplay);

  }

  private static String getDisplay(Brochure b) {
    String nl = System.getProperty("line.separator");
    StringBuilder sb = new StringBuilder();
    sb.append(nl + "Brochure");
    for (Map.Entry<String, Course> entry : b.coursesByIdMap.entrySet()) {
      Course course = entry.getValue();
      sb.append(nl + "  coursesByIdMap.entry");
      sb.append(nl + "    key:   String(" + entry.getKey() + ")");
      sb.append(nl + "    value: Course(id=" + course.id + ", name=" + course.name + ")");
    }
    return sb.toString();
  }

}

Output is:

Brochure
  coursesByIdMap.entry
    key:   String(cs519)
    value: Course(id=cs519, name=Network Security)
  coursesByIdMap.entry
    key:   String(cs501)
    value: Course(id=cs501, name=Software Engineering)
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<brochure>
    <courses>
        <course id="cs519">
            <name>Network Security</name>
        </course>
        <course id="cs501">
            <name>Software Engineering</name>
        </course>
    </courses>
</brochure>


Brochure
  coursesByIdMap.entry
    key:   String(cs519)
    value: Course(id=cs519, name=Network Security)
  coursesByIdMap.entry
    key:   String(cs501)
    value: Course(id=cs501, name=Software Engineering)

So now how can you do it without that crutch object?

A: 

The example from your link doesn't work - here are two links which discuss how you can get the results you're looking for:

http://old.nabble.com/XmlJavaTypeAdapter-help-td19127284.html

http://forums.java.net/jive/message.jspa?messageID=267376

Note that there is a minor problem with your main() method, I've highlighted the fix:

public static void main(String[] args) {
        Brochure b = new Brochure();
        Course c = new Course();
        c.id = "cs501";
        c.name = "Software Engineering";
        b.courses = new HashMap<String, Course>();
        b.courses.put(c.id, c);
        c = new Course() // You need to add this
        c.id = "cs519";
        c.name = "Network Security";
        b.courses.put(c.id, c);

        System.out.println(convertObjectToXml(Brochure.class, b));

}
mtpettyp
I've updated the question to fix the error. Thanks!
TJ