为什么jaxb 2.2无法处理元素及其子元素具有相同ID的情况? [英] Why jaxb 2.2 can not handle the case that an element and its sub element have equal IDs?
问题描述
我有一个对象保存为XML,读取该XML,并保存到另一个XML。 2个XML文件是不同的。
I have an object saved as an XML, read that XML, and save to another XML. The 2 XML files are different.
第一个XML(我的预期):
The first XML (My expected):
<?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:
If I change the sub element ID:
第一个XML(我的预期):
The first XML (My expected):
<?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>
第二个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>
这很奇怪。
谁可以告诉我原因?
It's strange. Who can tell me why?
示例代码:
/*
* 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);
}
}
推荐答案
注意:我是 EclipseLink JAXB(MOXy) 领导和 JAXB(JSR-222)的成员 专家组。
Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB (JSR-222) expert group.
JAXB RI问题
JAXB 2.2(JSR-222)可以处理这个用例,但是正在使用的特定JAXB实现中存在一个错误,它阻止了它的工作。我已经能够确认您使用JDK 1.7.0中包含的JAXB 2.2实现的问题。我建议为这个问题打开一个错误:
JAXB 2.2 (JSR-222) can handle this use case, but there happens to be a bug in the particular JAXB implementation that you are using that is preventing it from working. I have been able to confirm the issue that you are seeing using the JAXB 2.2 implementation included in JDK 1.7.0 for the Mac. I would recommend opening a bug for this issue:
- http://java.net/jira/browse/JAXB/
其他JAXB实现
我已经使用EclipseLink JAXB(MOXy)尝试了示例代码,并按预期运行。我是MOXy的主角,你可以从以下位置下载它。
I have tried your sample code with EclipseLink JAXB (MOXy) and it runs as expected. I'm the MOXy lead and you can download it from the following location.
- http://www.eclipse.org/eclipselink/downloads/
更多信息
- http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html
这篇关于为什么jaxb 2.2无法处理元素及其子元素具有相同ID的情况?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!