Jaxb должен Marshalling внутренних классов? - PullRequest
1 голос
/ 28 июня 2011

Смотри, у меня есть этот кусок XSD:

<xs:complexType name="ResourcesType">
    <xs:sequence>
      <xs:element name="Classrooms">
        <xs:complexType mixed="true">
          <xs:sequence>
            <xs:element type="ResourceType" name="Resource" maxOccurs="unbounded" minOccurs="0"/>
          </xs:sequence>
        </xs:complexType>
      </xs:element>
      <xs:element name="Teachers">
        <xs:complexType mixed="true">
          <xs:sequence>
            <xs:element type="ResourceType" name="Resource" maxOccurs="unbounded" minOccurs="0"/>
          </xs:sequence>
        </xs:complexType>
      </xs:element>
      <xs:element name="Classes">
        <xs:complexType mixed="true">
          <xs:sequence>
            <xs:element type="ResourceType" name="Resource" maxOccurs="unbounded" minOccurs="0"/>
          </xs:sequence>
        </xs:complexType>
      </xs:element>
      <xs:element name="Special">
        <xs:simpleType>
          <xs:restriction base="xs:string">
            <xs:enumeration value="0"/>
            <xs:enumeration value=""/>
          </xs:restriction>
        </xs:simpleType>
      </xs:element>
    </xs:sequence>
  </xs:complexType>

Я сгенерировал классы из схемы, используя плагин eclipse, и получил это:

ResourcesType класс с Classes, ClassRooms и Teachers внутренними классами. Во всех этих внутренних классах я защищал List<Serializable> поле содержимого. Также генерируются ClassesType, ClassRoomsType и TeachersType как обычные классы.

Почему сформировались эти внутренние классы? Как бы мне установить этот список, если другие классы не сериализуемы?

Спасибо
С наилучшими пожеланиями

1 Ответ

3 голосов
/ 28 июня 2011

Почему сгенерированы эти внутренние классы?

Реализация JAXB будет внутренними классами для анонимных сложных типов.Это делается для того, чтобы уменьшить вероятность конфликтов имен генерируемых классов.

<xs:complexType name="ResourcesType">
    <xs:sequence>
      <xs:element name="Classrooms">
        <xs:complexType mixed="true">
          <xs:sequence>
            <xs:element type="ResourceType" name="Resource" maxOccurs="unbounded" minOccurs="0"/>
          </xs:sequence>
        </xs:complexType>
      </xs:element>
      ...
    </xs:sequence>

    </xs:complexType>

Как установить этот список, если другие классы не сериализуемы?

Допустимое содержимое свойства content: JAXBElement<ResourceType> и String.Serializable - это общий интерфейс для обоих этих типов, который немного более строг, чем Object.

<code>@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
    "content"
})
public static class Classes {

    @XmlElementRef(name = "Resource", type = JAXBElement.class)
    @XmlMixed
    protected List<Serializable> content;

    /**
     * Gets the value of the content property.
     * 
     * <p>
     * This accessor method returns a reference to the live list,
     * not a snapshot. Therefore any modification you make to the
     * returned list will be present inside the JAXB object.
     * This is why there is not a <CODE>set</CODE> method for the content property.
     * 
     * <p>
     * For example, to add a new item, do as follows:
     * <pre>
     *    getContent().add(newItem);
     * 
* * *

* Объекты следующих типов разрешены в списке * {@link JAXBElement} {@ code <} {@ link ResourceType} {@ code>} * {@link String} * * * / public List getContent () {if (content == null) {content = new ArrayList ();} вернуть this.content;}}

ОБНОВЛЕНИЕ

Может помочь следующий пример:

package example;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.Marshaller;
import javax.xml.namespace.QName;

import example.ResourcesType.Classrooms;

public class Demo {

    public static void main(String[] args) throws Exception {
        // This is the ObjectFactory that was generated by XJC
        ObjectFactory objectFactory = new ObjectFactory();

        // You can instantiate objects using the constructors
        ResourcesType resourcesType = new ResourcesType();

        // You can instantiate objects using the ObjectFactory
        Classrooms classRooms = objectFactory.createResourcesTypeClassrooms();
        resourcesType.setClassrooms(classRooms);

        // You can use the ObjectFactory to wrap an object in a JAXBElement
        ResourceType resourceType1 = new ResourceType();
        JAXBElement<ResourceType> jaxbElement1 = objectFactory.createResourcesTypeClassesResource(resourceType1);
        classRooms.getContent().add(jaxbElement1);

        ResourceType resourceType2 = objectFactory.createResourceType();
        JAXBElement<ResourceType> jaxbElement2 = objectFactory.createResourcesTypeClassesResource(resourceType2);
        classRooms.getContent().add(jaxbElement2);

        // You can create a JAXBContext on the package name of your generated classes
        JAXBContext jc = JAXBContext.newInstance("example");

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

        // You can also create an instance of JAXBElement without using the ObjectFactory
        JAXBElement<ResourcesType> rootElement = new JAXBElement<ResourcesType>(new QName("root"), ResourcesType.class, resourcesType);
        marshaller.marshal(rootElement, System.out);
    }

}
...