1

I have two classes at the moment. Customer and CustomerItem, each Customer can contain multiple CustomerItems:

@XmlRootElement(name = "Customer")
@XmlAccessorType(XmlAccessType.FIELD)
public class Customer implements Serializable {

  private final String customerNumber;
  private final String customerName;

    @XmlElementWrapper(name = "customerItems")
    @XmlElement(name = "CustomerItem")
    private List<CustomerItem> customerItems;
...

Via REST we can get a List<Customer>, which will result in an XML looking like that:

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
 <collection>
  <Customer>
    // normal values
    <customerItems> 
      <customerItem>
        // normal values
      </customerItem>
    </customerItems>
  </Customer>
  <Customer>
    ...
  </Customer>
  <Customer>
    ...
  </Customer>
</collection>

Now if I want to unmarshal the response I get an error:

javax.xml.bind.UnmarshalException: unexpected element (uri:"", local:"collection"). Expected elements are <{}Customer>,<{}CustomerItem>

private List<Customer> getCustomersFromResponse(HttpResponse response)
    throws JAXBException, IllegalStateException, IOException {

    JAXBContext jaxbContext = JAXBContext.newInstance(Customer.class);
    Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
    InputStream content = response.getEntity().getContent();
    InputStreamReader reader = new InputStreamReader(content);

    java.util.List<Customer> unmarshal = (List<Customer>) jaxbUnmarshaller.unmarshal(reader);
    return unmarshal;

}

Now I know why it's not working, obviously Jaxb expects Customer to be the root element, but now find a collection (which seems to be a default value when a List gets returned?).

A workaround would be to create a new Customers class which contains a list of customer and make it the root element, but actually I wouldn't want a new class.

There must be a way to tell jaxb that I have a list of the classes I want to get and that he should look inside the collection tag or something like that?!

Core_F
  • 3,372
  • 3
  • 30
  • 53

1 Answers1

1

I see here two ways.

1) Create special wrapper class with @XmlRootElement(name = "collection") and set it against unmarshaller.

2) Another way - split input xml into smaller one using simple SAX parser implementation and then parse each fragment separately with JAXB (see: Split 1GB Xml file using Java).

I don't think that you can simply tell JAXB: parse me this xml as set of elements of type XXX.

Community
  • 1
  • 1
Andremoniy
  • 34,031
  • 20
  • 135
  • 241