为什么 JAXB 不能正确处理命名空间子元素?
我将 JAXB 与 CXF Web 服务结合使用。当我将: 传递
<?xml version="1.0" ?><ns2:Optionen xmlns:ns2="http://test.at/ezustellung/global/20090501#">
<ns2:PdfAKonvertierung>true</ns2:PdfAKonvertierung><ns2:SignaturTyp>Adobe</ns2:SignaturTyp>
</ns2:Optionen>
给 Unmarshaller 时,我的对象中的属性 pdfAKonvertierung 和 SignaturTyp 均为 null。但如果我通过了:
<?xml version="1.0" ?><ns2:Optionen xmlns:ns2="http://test.at/ezustellung/global/20090501#">
<PdfAKonvertierung>true</PdfAKonvertierung><SignaturTyp>Adobe</SignaturTyp>
</ns2:Optionen>
根据 CXF 验证器和 ,这是无效的维基百科(翻译,还没有找到英文):
具有名称空间前缀的元素的子元素不会自动具有相同的名称空间,它们也必须带有名称空间前缀。
相应地设置属性。有人可以发现我的代码中的错误,或者我是否在 Java 1.6 的 JAXB 实现中发现了错误?
作为参考,这是我的代码:
public class JaxbTests {
@Test
public void testOptionen() throws JAXBException, SAXException, IOException {
JAXBContext context = JAXBContext.newInstance(Optionen.class);
Unmarshaller unmarshaller = context.createUnmarshaller();
ByteArrayInputStream is = new ByteArrayInputStream(
// Does not work
("<?xml version=\"1.0\" ?><ns2:Optionen xmlns:ns2=\"http://test.at/ezustellung/global/20090501#\">" +
"<ns2:PdfAKonvertierung>true</ns2:PdfAKonvertierung><ns2:SignaturTyp>Adobe</ns2:SignaturTyp>" +
"</ns2:Optionen>").getBytes());
// Works
// ("<?xml version=\"1.0\" ?><ns2:Optionen xmlns:ns2=\"http://test.at/ezustellung/global/20090501#\">" +
// "<PdfAKonvertierung>true</PdfAKonvertierung><SignaturTyp>Adobe</SignaturTyp>" +
// "</ns2:Optionen>").getBytes());
Optionen opts = ((Optionen) unmarshaller.unmarshal(is));
Assert.assertTrue(opts.isPdfAKonvertierung() == true);
Assert.assertEquals(SignaturTypType.ADOBE, opts.getSignaturTyp());
}
}
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
"pdfAKonvertierung",
"signaturTyp"
})
@XmlRootElement(name = "Optionen")
public class Optionen {
@XmlElement(name = "PdfAKonvertierung", defaultValue = "true")
protected Boolean pdfAKonvertierung;
@XmlElement(name = "SignaturTyp", defaultValue = "Adobe")
protected SignaturTypType signaturTyp;
public Optionen() {
System.out.println("Optionen created");
}
public Boolean isPdfAKonvertierung() {
return pdfAKonvertierung;
}
public void setPdfAKonvertierung(Boolean value) {
this.pdfAKonvertierung = value;
}
public SignaturTypType getSignaturTyp() {
return signaturTyp;
}
public void setSignaturTyp(SignaturTypType value) {
this.signaturTyp = value;
}
}
@XmlType(name = "SignaturTypType")
@XmlEnum
public enum SignaturTypType {
@XmlEnumValue("Adobe")
ADOBE("Adobe"), @XmlEnumValue("PDF-AS")
PDF_AS("PDF-AS");
private final String value;
SignaturTypType(String v) {
this.value = v;
}
public String value() {
return this.value;
}
public static SignaturTypType fromValue(String v) {
for (SignaturTypType c : SignaturTypType.values()) {
if (c.value.equals(v)) {
return c;
}
}
throw new IllegalArgumentException(v);
}
}
package-info.java:
@javax.xml.bind.annotation.XmlSchema(namespace = "http://test.at/ezustellung/global/20090501#")
package at.test.ezustellung.global._20090501_;
I'm using JAXB with a CXF Web Service. When I pass:
<?xml version="1.0" ?><ns2:Optionen xmlns:ns2="http://test.at/ezustellung/global/20090501#">
<ns2:PdfAKonvertierung>true</ns2:PdfAKonvertierung><ns2:SignaturTyp>Adobe</ns2:SignaturTyp>
</ns2:Optionen>
to the Unmarshaller, the properties pdfAKonvertierung und signaturTyp are both null in my Object. But if I pass:
<?xml version="1.0" ?><ns2:Optionen xmlns:ns2="http://test.at/ezustellung/global/20090501#">
<PdfAKonvertierung>true</PdfAKonvertierung><SignaturTyp>Adobe</SignaturTyp>
</ns2:Optionen>
which is invalid, according to the CXF Validator and wikipedia (translation, haven't found that in english):
Child elements of an element with a namespace prefix do not automatically have the same namespace, they have to be prefixed with a namespace as well.
The properties are set accordingly. Can someone spot an error in my code, or have I found a bug in the JAXB implementation from Java 1.6?
For reference, here is my code:
public class JaxbTests {
@Test
public void testOptionen() throws JAXBException, SAXException, IOException {
JAXBContext context = JAXBContext.newInstance(Optionen.class);
Unmarshaller unmarshaller = context.createUnmarshaller();
ByteArrayInputStream is = new ByteArrayInputStream(
// Does not work
("<?xml version=\"1.0\" ?><ns2:Optionen xmlns:ns2=\"http://test.at/ezustellung/global/20090501#\">" +
"<ns2:PdfAKonvertierung>true</ns2:PdfAKonvertierung><ns2:SignaturTyp>Adobe</ns2:SignaturTyp>" +
"</ns2:Optionen>").getBytes());
// Works
// ("<?xml version=\"1.0\" ?><ns2:Optionen xmlns:ns2=\"http://test.at/ezustellung/global/20090501#\">" +
// "<PdfAKonvertierung>true</PdfAKonvertierung><SignaturTyp>Adobe</SignaturTyp>" +
// "</ns2:Optionen>").getBytes());
Optionen opts = ((Optionen) unmarshaller.unmarshal(is));
Assert.assertTrue(opts.isPdfAKonvertierung() == true);
Assert.assertEquals(SignaturTypType.ADOBE, opts.getSignaturTyp());
}
}
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
"pdfAKonvertierung",
"signaturTyp"
})
@XmlRootElement(name = "Optionen")
public class Optionen {
@XmlElement(name = "PdfAKonvertierung", defaultValue = "true")
protected Boolean pdfAKonvertierung;
@XmlElement(name = "SignaturTyp", defaultValue = "Adobe")
protected SignaturTypType signaturTyp;
public Optionen() {
System.out.println("Optionen created");
}
public Boolean isPdfAKonvertierung() {
return pdfAKonvertierung;
}
public void setPdfAKonvertierung(Boolean value) {
this.pdfAKonvertierung = value;
}
public SignaturTypType getSignaturTyp() {
return signaturTyp;
}
public void setSignaturTyp(SignaturTypType value) {
this.signaturTyp = value;
}
}
@XmlType(name = "SignaturTypType")
@XmlEnum
public enum SignaturTypType {
@XmlEnumValue("Adobe")
ADOBE("Adobe"), @XmlEnumValue("PDF-AS")
PDF_AS("PDF-AS");
private final String value;
SignaturTypType(String v) {
this.value = v;
}
public String value() {
return this.value;
}
public static SignaturTypType fromValue(String v) {
for (SignaturTypType c : SignaturTypType.values()) {
if (c.value.equals(v)) {
return c;
}
}
throw new IllegalArgumentException(v);
}
}
package-info.java:
@javax.xml.bind.annotation.XmlSchema(namespace = "http://test.at/ezustellung/global/20090501#")
package at.test.ezustellung.global._20090501_;
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
问题的解决方案(不修改生成的类)是确保该
属性存在并重新生成 jaxb 映射,因此
最终
出现在 package-info.java 中
The solution (without modifying the generated classes) to the problem was to make sure that the
attribute is present and to regenerate the jaxb mapping, so
that
ends up in the package-info.java
阅读格式不正确的代码有点困难,但是如果您使用正确的命名空间声明元素,例如
@XmlElement(namespace = "http://test.at/ezustellung/全局/20090501#",名称 = "SignaturTyp",defaultValue = "Adobe")
?It's a little bit difficult to read your incorrectly formatted code, but wouldn't it fix your problem if you declare your elements with the correct namespace, e.g.
@XmlElement(namespace = "http://test.at/ezustellung/global/20090501#", name = "SignaturTyp", defaultValue = "Adobe")
?