为什么 JAXB 不能正确处理命名空间子元素?

发布于 2024-08-24 21:01:36 字数 3617 浏览 2 评论 0原文

我将 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

半世晨晓 2024-08-31 21:01:36

问题的解决方案(不修改生成的类)是确保该

<xs:schema elementFormDefault="qualified">

属性存在并重新生成 jaxb 映射,因此
最终

elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED

出现在 package-info.java 中

The solution (without modifying the generated classes) to the problem was to make sure that the

<xs:schema elementFormDefault="qualified">

attribute is present and to regenerate the jaxb mapping, so
that

elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED

ends up in the package-info.java

小耗子 2024-08-31 21:01:36

阅读格式不正确的代码有点困难,但是如果您使用正确的命名空间声明元素,例如 @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")?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文