2

好吧,当我执行以下操作时会发生什么:

Entities.java:所有名称以“E”开头的类(例如 ESTudent、ETeacher 等)都扩展了EntityWithId类。

public class Entities {

  Map<Integer,EStudent> students;
  Map<Integer,ETeacher> teachers;
  Map<Integer,ECourse> courses;
  Map<Integer,EQuiz> quizzes;
  Map<Integer,EQuestion> questions;
  Map<Integer,EAnswer> answers;
  Map<Integer,ETimeslot> timeslots;
  Map<Integer,ESharedFile> sharedFiles;

  ...
}

entity-xml-bindings.xml:我为所有属性设置了 xml-java-type-adapter。为清楚起见省略。

<?xml version="1.0" encoding="US-ASCII"?>
  <xml-bindings xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
    package-name="com.pest.esinif.common.entity">

<java-types>
    <java-type name="Entities">
        <java-attributes>
            <xml-element java-attribute="students" >
                <xml-java-type-adapter value="com.pest.esinif.common.entity.adapters.MapToCollectionAdapter" />
            </xml-element>
            ...
        </java-attributes>
    </java-type>
</java-types>
</xml-bindings>

MapToCollectionAdapter.java:旨在将 Maps 转换为 Collections。

public class MapToCollectionAdapter extends XmlAdapter<MyCollection, Map<Integer,EntityWithId>> {

@Override
public Map<Integer, EntityWithId> unmarshal(MyCollection v) throws Exception {
    Map<Integer, EntityWithId> m = new TreeMap<>();

    for (Iterator<EntityWithId> it = v.list.iterator(); it.hasNext();) {
        EntityWithId i = it.next();
        m.put(i.getId(), i);
    }

    return m;
}

@Override
public MyCollection marshal(Map<Integer, EntityWithId> v) throws Exception {
    if(v == null) {
        return null;
    }
    MyCollection mc = new MyCollection();
    mc.list = v.values();
    return mc;
}

class MyCollection {

  @XmlElement(name="entry")
  public Collection<EntityWithId> list;

  public MyCollection() {}
}

当我编组这个时,输出如下。

<?xml version="1.0" encoding="UTF-8"?>
<entities>
   <courses>
      <entry id="4" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="eCourse">
         <name>English</name>
         <timetable>5</timetable>
         <timetable>6</timetable>
      </entry>
   </courses>
   <students>
      <entry id="1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="eStudent">
         <name>Anil Anar</name>
      </entry>
   </students>
   <timeslots>
      <entry id="12" course="4" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="eTimeslot">
         <attendances>1</attendances>
         <day>1970-01-01T02:00:00.0</day>
         <slot>0</slot>
      </entry>
   </timeslots>
</entities>

你注意到那些xsi:types了吗?当我省略它们时, unmarshaller 显然失败了。但我不希望所有<entry>标签都有这个。我希望它如下:

<courses child-xsi-type="eCourse">
    <entry> ... </entry>
    <entry> ... </entry>
</courses>

感谢帮助。

4

1 回答 1

0

感谢Blaise Doughan 的博客,我解决了这个问题。诀窍是使用@XmlAnyElement(lax=true)and 来注释EntityWithIdwith的子类@XmlRootElement

class MyCollection {

  @XmlAnyElement(lax=true)
  public Collection<EntityWithId> list;

  public MyCollection() {}
}

我得到的输出:

<?xml version="1.0" encoding="UTF-8"?>
<entities>
   <courses>
      <course id="4">
         <name>English</name>
         <timetable>5</timetable>
         <timetable>6</timetable>
      </course>
   </courses>
   <students>
      <student id="1">
         <name>Anil Anar</name>
      </student>
   </students>
   <timeslots>
      <timeslot id="12">
         <attendances>1</attendances>
         <day>1970-01-01T02:00:00.0</day>
         <slot>0</slot>
      </timeslot>
   </timeslots>
</entities>
于 2013-04-12T19:31:36.820 回答