Collection of complex object in XSD to generate POJO

I have to create an XSD so that I could generate a POJO to use in the code.(using jaxb2-maven-plugin)

That pojo will be used to populate the fields and then be serialized as XML to be sent to another service. (using XmlMapper)

I need to get the right way to create Collections of complex objects so that the XML generated looks like this:

<Request>
  <cars>
    <car>
      <name>golf</name>
      <engine>1.6</engine>
      <noOfSeats>5</noOfSeats>
    </car>
    <car>
      <name>polo</name>
      <engine>1.4</engine>
      <noOfSeats>5</noOfSeats>
    </car>
    <car> ... </car>
  </cars>
</Request>  

I have tried different solutions here and there but I am getting is results like:

Error 1

<Request>
  <cars>
    <car>
      <car>...</car>
      <car>...</car>
    </car>
  </cars>
</Request> 

or

Error 2

<Request>
  <cars>
    <cars>...</cars>
    <cars>...</cars>
  </cars>
</Request> 

it seems that I can’t get the right definition that would have a root list “cars” and items “car” and in pojo list of Car called cars.

here is a failed scenario but closest to what I need: XSD

  <xs:element name="Request">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="cars" type="car" minOccurs="0" maxOccurs="unbounded" />
      </xs:sequence>
    </xs:complexType>
  </xs:element>
  <xs:complexType name="car">
    <xs:sequence>
      <xs:element name="name" type="xs:string"/>
      ...
    </xs:sequence>
  </xs:complexType>
  

The generated Request class has list as

List<Car> cars;

Which is what I expect, but in the definition of Car there is no root name tag. so the scenario of error 2 shows up when serializing as XML

Here is the mapper I use

XmlMapper.builder()
  .addModule(new JaxbAnnotationModule())
  .configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false)
  .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
  .build();

using Java 8, spring boot 2 and maven

UPDATE I accepted the response below because it is correct and works. But I decided to put an update because my main issue was actually the serializer. the XmlMapper does not serialize the right way or the expected way rather. I finally used the following to have the correct result:

    public Jaxb2Marshaller mashaller() {
        Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
        marshaller.setClassesToBeBound(Request.class);
        return marshaller;
    }

Answer

Almost right – you just need to tweak the complex type definition for element ‘cars’. I think you (like many others) have failed to understand the difference between an element declaration and a type definition. An element declaration represents a tag. A type declaration specifies the rules for the content of a tag.

<xs:element name="Request">
    <xs:complexType>
        <xs:sequence>
            <xs:element name="cars"  minOccurs="0" maxOccurs="1">
                <xs:complexType>
                    <xs:sequence>
                        <xs:element ref="car" minOccurs="0" maxOccurs="unbounded"/>
                    </xs:sequence>
                </xs:complexType>
            </xs:element>
        </xs:sequence>
    </xs:complexType>
</xs:element>

<xs:element name="car">
    <xs:complexType>
        <xs:sequence>
            <xs:element name="name" type="xs:string"/>
            <xs:element name="engine" type="xs:string"/>
            <xs:element name="numberOfSeats" type="xs:int"/>
        </xs:sequence>
    </xs:complexType>
</xs:element>

Not tested, and the style could be improved, but hopefully you get the idea.

Leave a Reply

Your email address will not be published. Required fields are marked *