2014-10-27 117 views
2

我有以下代码:JAXB复杂的映射

@XmlRootElement(name = "repository") 
@XmlAccessorType(XmlAccessType.FIELD) 
public class Repository 
{ 
    @XmlElement (name = "id") 
    private String id; 

    @XmlElement (name = "policy") 
    private String policy; 
    ... 
} 

@XmlRootElement(name = "storage") 
@XmlAccessorType(XmlAccessType.FIELD) 
public class Storage 
{ 

    @XmlElement (name = "id") 
    private String id; 

    /** 
    * K: repository.id 
    * V: Repository 
    */ 
    @XmlElement (name = "repositories") 
    @XmlJavaTypeAdapter(RepositoryMapAdapter.class) 
    private Map<String, Repository> repositories = new LinkedHashMap<String, Repository>(); 
    ... 
} 

public class DataCenter 
{ 
    /** 
    * K: storageId 
    * V: storage 
    */ 
    @XmlElement(name = "storages") 
    @XmlJavaTypeAdapter(StorageMapAdapter.class) 
    //@XStreamAlias(value = "storages") 
    private Map<String, Storage> storages = new LinkedHashMap<String, Storage>(); 

    ... 
} 

我有以下两个适配器:

public class RepositoryMapAdapter 
     extends XmlAdapter<RepositoryMapAdapter.RepositoryMap, Map<String, Repository>> 
{ 

    public static class RepositoryMap 
    { 
     @XmlVariableNode("id") 
     List<RepositoryMapEntry> entries = new ArrayList<RepositoryMapEntry>(); 
    } 

    public static class RepositoryMapEntry 
    { 
     @XmlAttribute 
     public String id; 

     @XmlValue 
     public Repository repository; 
    } 

    @Override 
    public RepositoryMap marshal(Map<String, Repository> map) 
      throws Exception 
    { 
     RepositoryMap repositoryMap = new RepositoryMap(); 
     for (Map.Entry<String, Repository> entry : map.entrySet()) 
     { 
      RepositoryMapEntry repositoryMapEntry = new RepositoryMapEntry(); 
      repositoryMapEntry.id = entry.getKey(); 
      repositoryMapEntry.repository = entry.getValue(); 

      System.out.println("Writing repository " + entry.getValue().getId()); 

      repositoryMap.entries.add(repositoryMapEntry); 
     } 

     return repositoryMap; 
    } 

    @Override 
    public Map<String, Repository> unmarshal(RepositoryMap repositoryMap) 
      throws Exception 
    { 
     List<RepositoryMapEntry> adaptedEntries = repositoryMap.entries; 

     Map<String, Repository> map = new LinkedHashMap<String, Repository>(adaptedEntries.size()); 
     for (RepositoryMapEntry repositoryMapEntry : adaptedEntries) 
     { 
      System.out.println("Reading repository " + repositoryMapEntry.id); 
      map.put(repositoryMapEntry.id, repositoryMapEntry.repository); 
     } 

     return map; 
    } 

} 

public class StorageMapAdapter 
     extends XmlAdapter<StorageMapAdapter.StorageMap, Map<String, Storage>> 
{ 

    public static class StorageMap 
    { 
     @XmlVariableNode("id") 
     List<StorageMapEntry> entries = new ArrayList<StorageMapEntry>(); 
    } 

    public static class StorageMapEntry 
    { 
     @XmlAttribute 
     public String id; 

     @XmlValue 
     public Storage storage; 
    } 

    @Override 
    public StorageMap marshal(Map<String, Storage> map) 
      throws Exception 
    { 
     StorageMap storageMap = new StorageMap(); 
     for (Map.Entry<String, Storage> entry : map.entrySet()) 
     { 
      StorageMapEntry storageMapEntry = new StorageMapEntry(); 
      storageMapEntry.id = entry.getKey(); 
      storageMapEntry.storage = entry.getValue(); 

      System.out.println("Writing storage " + entry.getValue().getId()); 

      storageMap.entries.add(storageMapEntry); 
     } 

     return storageMap; 
    } 

    @Override 
    public Map<String, Storage> unmarshal(StorageMap storageMap) 
      throws Exception 
    { 
     List<StorageMapEntry> adaptedEntries = storageMap.entries; 

     Map<String, Storage> map = new LinkedHashMap<String, Storage>(adaptedEntries.size()); 
     for (StorageMapEntry storageMapEntry : adaptedEntries) 
     { 
      System.out.println("Reading storage " + storageMapEntry.id); 
      map.put(storageMapEntry.id, storageMapEntry.storage); 
     } 

     return map; 
    } 

} 

我想有以下XML

<storages> 
    <storage id="storage0"> 
     <repositories> 
      <repository id="repository1" policy="policy1"/> 
      <repository id="repository2" policy="policy2"/> 
     </repositories> 
    </storage> 
    <storage id="storage1"> 
     <repositories> 
      <repository id="repository3" /> 
      <repository id="repository4" /> 
     </repositories> 
    </storage> 
</storages> 

基于上述XML,我还需要做些什么才能让我的代码读/写如XML使用JAXB?据我所知,我需要使用XmlAdapter,但我不太清楚如何将其应用于此案例。

+1

'地图<字符串,资源库>':会是什么'key'是什么? – 2014-10-27 16:47:17

+0

是的,它将是'repository.id'。 – carlspring 2014-10-27 16:47:55

+2

如果你只是想读/写这个XML,使用List而不是Map会更容易绑定:是可行的吗? – 2014-10-27 16:48:29

回答

2

中的东西的行:

@XmlRootElement(name = "datacenter") 
public class DataCenter { 
    /** 
    * K: storageId V: storage 
    */ 
    @XmlElement(name = "storages") 
    @XmlJavaTypeAdapter(StorageMapAdapter.class) 
    private final Map<String, Storage> storages = new LinkedHashMap<String, Storage>(); 
} 

@XmlJavaTypeAdapter(StorageMapAdapter.class) 
@XmlAccessorType(XmlAccessType.FIELD) 
public class Storage { 

    @XmlAttribute(name = "id") 
    private String id; 

    /** 
    * K: repository.id V: Repository 
    */ 
    @XmlElement(name = "repositories") 
    @XmlJavaTypeAdapter(RepositoryMapAdapter.class) 
    private final Map<String, Repository> repositories = new LinkedHashMap<String, Repository>(); 

} 

public class StorageMap { 
    @XmlElement(name = "storage") 
    List<Storage> entries = new ArrayList<Storage>(); 

    public List<Storage> getEntries() { 
     return entries; 
    } 
} 

public class StorageMapAdapter extends XmlAdapter<StorageMap, Map<String, Storage>> { 

    @Override 
    public StorageMap marshal(Map<String, Storage> map) throws Exception { 
     StorageMap storageMap = new StorageMap(); 
     for (Map.Entry<String, Storage> entry : map.entrySet()) { 
      storageMap.getEntries().add(entry.getValue()); 
     } 
     return storageMap; 
    } 

    @Override 
    public Map<String, Storage> unmarshal(StorageMap storageMap) throws Exception { 
     List<Storage> adaptedEntries = storageMap.entries; 
     Map<String, Storage> map = new LinkedHashMap<String, Storage>(adaptedEntries.size()); 
     for (Storage storage : adaptedEntries) { 
      map.put(storage.getId(), storage); 
     } 
     return map; 
    } 
} 

@XmlRootElement(name = "repository") 
@XmlAccessorType(XmlAccessType.FIELD) 
public class Repository { 
    @XmlAttribute(name = "id") 
    private String id; 

    @XmlAttribute(name = "policy") 
    private String policy; 
} 

public class RepositoryMap { 
    @XmlElement(name = "repository") 
    List<Repository> entries = new ArrayList<Repository>(); 

    public List<Repository> getEntries() { 
     return entries; 
    } 
} 

public class RepositoryMapAdapter extends XmlAdapter<RepositoryMap, Map<String, Repository>> { 

    @Override 
    public RepositoryMap marshal(Map<String, Repository> map) throws Exception { 
     RepositoryMap repositoryMap = new RepositoryMap(); 
     for (Map.Entry<String, Repository> entry : map.entrySet()) { 
      repositoryMap.getEntries().add(entry.getValue()); 
     } 
     return repositoryMap; 
    } 

    @Override 
    public Map<String, Repository> unmarshal(RepositoryMap repositoryMap) throws Exception { 
     List<Repository> adaptedEntries = repositoryMap.entries; 
     Map<String, Repository> map = new LinkedHashMap<String, Repository>(adaptedEntries.size()); 
     for (Repository repository : adaptedEntries) { 
      System.out.println("Reading repository " + repository.getId()); 
      map.put(repository.getId(), repository); 
     } 
     return map; 
    } 
} 

运行演示在这里:http://ideone.com/NyOGVQ 演示与编组这里更新:http://ideone.com/NzvRzX

+0

感谢您的回答。我稍微更新/更改了这个问题。你能帮助我做到这一点吗? – carlspring 2014-10-27 20:18:27

+0

@carlspring此刻哪些更新代码无法使用? (我建议将RepositoryMap和RepositoryEntry移出适配器,而非静态的,因为我记得我在内部类中有jaxb解组元素的问题)。 – 2014-10-27 23:44:03

+0

存储/解析XML时,''为空。 – carlspring 2014-10-28 00:05:58