2012-10-10 18 views
1

我有一個對象保存爲XML,讀取該XML,並保存到另一個XML。這2個XML文件是不同的。爲什麼jaxb 2.2無法處理元素及其子元素具有相同ID的情況?

第一XML(我的預期):

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<multiIDTest> 
    <containerList> 
     <container id="1"> 
      <elem id="1"/> 
     </container> 
     <container container="1" id="2"/> 
     <container container="2" id="3"/> 
    </containerList> 
</multiIDTest> 

第二XML:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<multiIDTest> 
    <containerList> 
     <container id="1"> 
      <elem id="1"/> 
     </container> 
     <container id="2"/> 
     <container container="2" id="3"/> 
    </containerList> 
</multiIDTest> 

如果我改變子元件ID:

第一XML(我的預期):

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<multiIDTest> 
    <containerList> 
     <container id="1"> 
      <elem id="2"/> 
     </container> 
     <container container="1" id="2"/> 
     <container container="2" id="3"/> 
    </containerList> 
</multiIDTest> 

The第二個XML:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<multiIDTest> 
    <containerList> 
     <container id="1"> 
      <elem id="2"/> 
     </container> 
     <container container="1" id="2"/> 
     <container container="2" id="3"/> 
    </containerList> 
</multiIDTest> 

這很奇怪。 誰能告訴我爲什麼?

樣本代碼:

/* 
* To change this template, choose Tools | Templates 
* and open the template in the editor. 
*/ 
package xml; 

import java.io.File; 
import java.util.ArrayList; 
import java.util.List; 
import javax.xml.bind.JAXBContext; 
import javax.xml.bind.JAXBException; 
import javax.xml.bind.Marshaller; 
import javax.xml.bind.annotation.*; 

@XmlRootElement 
public class MultiIDTest { 

    static public class Element { 
     private String id; 

     @XmlID 
     @XmlAttribute(required=true) 
     public String getId() { 
      return id; 
     } 

     public void setId(String id) { 
      this.id = id; 
     } 
    } 

    static public class Container { 
     private String id; 

     @XmlID 
     @XmlAttribute(required=true) 
     public String getId() { 
      return id; 
     } 

     public void setId(String id) { 
      this.id = id; 
     } 

     private Container container; 

     @XmlIDREF 
     @XmlAttribute(required=true) 
     public Container getContainer() { 
      return container; 
     } 

     public void setContainer(Container e) { 
      this.container = e; 
     } 

     private Element elem; 

     public Element getElem() { 
      return elem; 
     } 

     public void setElem(Element e) { 
      this.elem = e; 
     } 
    } 

    static public class XmlSerialization { 
     public static Object read(String filepath, Class... classesToBeBound) { 
      try { 
       return JAXBContext.newInstance(classesToBeBound).createUnmarshaller().unmarshal(new File(filepath)); 
      } catch (JAXBException ex) {} 
      return null; 
     } 

     public static void write(String filePath, Object entity, Class... classesToBeBound) { 
      try { 
       Marshaller m = JAXBContext.newInstance(classesToBeBound).createMarshaller(); 
       m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); 
       m.marshal(entity, new File(filePath)); 
      } catch (JAXBException ex) {} 
     } 

    } 
    List<Container> containerList = new ArrayList<>(); 
    @XmlElementWrapper(name="containerList") 
    @XmlElement(name="container") 
    public List<Container> getContainerList() { 
     return (containerList != null)?containerList:(containerList = new ArrayList<>()); 
    } 

    public void setContainerList(List<Container> containerList) { 
     this.containerList = containerList; 
    } 
    public void initialize() { 
     Container container = new Container(); 
     container.setId("1"); 
     Element elem = new Element(); 
     elem.setId("2"); // if I use elem.setId("1"), problem occurs. 
     container.setElem(elem); 

     containerList.add(container); 
     Container container2 = new Container(); 
     container2.setId("2"); 
     container2.setContainer(container); 
     containerList.add(container2); 

     Container container3 = new Container(); 
     container3.setId("3"); 
     container3.setContainer(container2); 
     containerList.add(container3); 
    } 
    public void write(String filePath, Object obj) { 
     XmlSerialization.write(filePath, obj, MultiIDTest.class, Container.class, Element.class); 
    } 
    public Object read(String filePath) { 
     return XmlSerialization.read(filePath, MultiIDTest.class, Container.class, Element.class); 
    } 

    public static void main(String[] args) { 
     MultiIDTest test = new MultiIDTest(); 
     String filePath = "c:\\tmp.xml"; 
     test.initialize(); 
     test.write(filePath, test); 
     MultiIDTest test2 = (MultiIDTest)test.read(filePath); 
     test.write("c:\\tmp2.xml", test2); 
    } 
} 

回答

1

注:我是EclipseLink JAXB (MOXy)鉛和JAXB (JSR-222)專家小組的成員。

JAXB RI發行

JAXB 2.2(JSR-222)能夠處理這種使用情況,但恰好是您正在使用的特定JAXB實現中的錯誤是防止它的工作。我已經能夠確認使用包含在JDK 1.7.0中的JAXB 2.2實現Mac的問題。我會建議開一個bug針對此問題:

其他JAXB實現

我曾嘗試你的樣本代碼的EclipseLink JAXB(莫西),它運行正常。我是MOXy的領導者,你可以從以下位置下載它。

更多信息

+0

OK,非常感謝。我會嘗試MOXY。 – newda

相關問題