JAXB 绑定文件:XmlAdapters 和包名称

发布于 2024-10-23 13:40:29 字数 1251 浏览 2 评论 0原文

我有一个像这样的绑定文件

<jxb:bindings version="2.0" xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <jxb:bindings schemaLocation="example.xsd" node="/xs:schema">
    <jxb:schemaBindings>
        <jxb:package name="example" />
    </jxb:schemaBindings>
    <jxb:globalBindings>
        <jxb:javaType name="java.util.Calendar" xmlType="xs:dateTime"
            parseMethod="javax.xml.bind.DatatypeConverter.parseDateTime"
            printMethod="javax.xml.bind.DatatypeConverter.printDateTime" />
        <jxb:javaType name="java.util.Calendar" xmlType="xs:date"
            parseMethod="javax.xml.bind.DatatypeConverter.parseDate"
            printMethod="javax.xml.bind.DatatypeConverter.printDate" />
        <jxb:javaType name="java.util.Calendar" xmlType="xs:time"
            parseMethod="javax.xml.bind.DatatypeConverter.parseTime"
            printMethod="javax.xml.bind.DatatypeConverter.printTime" />
    </jxb:globalBindings>

  </jxb:bindings>
</jxb:bindings>

架构类是在“example”中生成的(正确),但 XmlAdapters 在“org.w3._2001.xmlschema”中生成(错误)。我该如何解决这个问题?

I have a binding file like this

<jxb:bindings version="2.0" xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <jxb:bindings schemaLocation="example.xsd" node="/xs:schema">
    <jxb:schemaBindings>
        <jxb:package name="example" />
    </jxb:schemaBindings>
    <jxb:globalBindings>
        <jxb:javaType name="java.util.Calendar" xmlType="xs:dateTime"
            parseMethod="javax.xml.bind.DatatypeConverter.parseDateTime"
            printMethod="javax.xml.bind.DatatypeConverter.printDateTime" />
        <jxb:javaType name="java.util.Calendar" xmlType="xs:date"
            parseMethod="javax.xml.bind.DatatypeConverter.parseDate"
            printMethod="javax.xml.bind.DatatypeConverter.printDate" />
        <jxb:javaType name="java.util.Calendar" xmlType="xs:time"
            parseMethod="javax.xml.bind.DatatypeConverter.parseTime"
            printMethod="javax.xml.bind.DatatypeConverter.printTime" />
    </jxb:globalBindings>

  </jxb:bindings>
</jxb:bindings>

The schema class are generated in "example" (correct), but the XmlAdapters in "org.w3._2001.xmlschema" (wrong). How can I fix this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

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

发布评论

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

评论(5

音盲 2024-10-30 13:40:30

对于 Apache CXF 用户,最简洁的方法是使用 wsdl2java 提供的 -p 选项。

-p [wsdl-namespace=]包名称

指定零个或多个用于生成的代码的包名称。
(可选)指定 WSDL 命名空间来封装名称映射。

在我们的例子中

-p http://www.w3.org/2001/XMLSchema=org.acme.foo

如果您使用 cxf-codegen-plugin,则只需添加另一对 ;

<plugin>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-codegen-plugin</artifactId>
    <version>${cxf.version}</version>
        [...]
    <extraarg>-p</extraarg>
    <extraarg>http://www.w3.org/2001/XMLSchema=org.acme.foo</extraarg>
        [...]
</plugin>

不需要 targetNamespace 指向保留的 XSD 命名空间,也不需要包罗万象的 jaxb 包绑定。

For Apache CXF users, the cleanest way is to use the -p option offered by wsdl2java.

-p [wsdl-namespace=]PackageName

Specifies zero, or more, package names to use for the generated code.
Optionally specifies the WSDL namespace to package name mapping.

In our case

-p http://www.w3.org/2001/XMLSchema=org.acme.foo

If you use the cxf-codegen-plugin, then just add another pair of <extraarg>.

<plugin>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-codegen-plugin</artifactId>
    <version>${cxf.version}</version>
        [...]
    <extraarg>-p</extraarg>
    <extraarg>http://www.w3.org/2001/XMLSchema=org.acme.foo</extraarg>
        [...]
</plugin>

No need for a targetNamespace pointing at the reserved XSD namespace and no need for catch-all jaxb package binding.

何以畏孤独 2024-10-30 13:40:30

使用 GlobalBinding 的更好方法是指定显式适配器,而不是使用此解析/打印对。例如,不要使用以下内容: 相反

<jaxb:javaType name="java.lang.Long" xmlType="xs:long"
                      parseMethod="com.mypackage.myclass.parseLong"
                  printMethod="com.mypackage.myclass.print"/>

,您应该:

<xjc:javaType name="java.lang.Long" xmlType="xs:long"
                  adapter="com.mypackage.LongAdapter"/>

记住为 xjc 添加命名空间:

xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
          jxb:extensionBindingPrefixes="xjc"

LongAdapter 类将如下所示:

public class LongAdapter
extends XmlAdapter<String, Long>
{


public Long unmarshal(String value) {
    return your_util_class.parseLong(value);
}

public String marshal(Long value) {
    return your_util_class.print(value);
}

}

这样,由于您显式指定了适配器类,因此 jaxb 将不会使用默认包生成默认适配器名称 org.w3._2001.xmlschema。

避免使用默认包名称 org.w3._2001.xmlschema 非常重要。举一个例子,如果您有一个项目 A 和一个项目 B,并且它们都有一些架构和绑定。在旧的方式中,它们都生成具有完全相同的完整限定名称的适配器,例如org.w3._2001.xmlschema.Adapter1。然而,这个适配器可能适用于项目 A 中的 Long 和项目 B 中的 Integer。然后,假设您有一个同时使用 A 和 B 的下游项目 C。现在问题变得很严重。如果 C 需要使用 Adapter1,您无法预测所使用的适配器是来自 A(Long)还是 B(Integer)。然后,您的应用程序 C 在某些时候可能工作正常,但在其他情况下可能会以奇怪的方式失败。如果发生这种情况,类型异常将类似于:

org.w3._2001.xmlschema.Adapter1 is not applicable to the field type java.lang.Double...

即使理论是正确的,当我在我的环境中使用 maven-jaxb2-plugin 尝试时,Roy Truelove 提到的解决方案似乎不起作用。

The better way to use GlobalBinding is to specify explicit adapter instead of using this parse/print pair. For example, instead of the following:

<jaxb:javaType name="java.lang.Long" xmlType="xs:long"
                      parseMethod="com.mypackage.myclass.parseLong"
                  printMethod="com.mypackage.myclass.print"/>

Instead, you should:

<xjc:javaType name="java.lang.Long" xmlType="xs:long"
                  adapter="com.mypackage.LongAdapter"/>

Remember to add namespace for xjc:

xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
          jxb:extensionBindingPrefixes="xjc"

The class LongAdapter would be like this:

public class LongAdapter
extends XmlAdapter<String, Long>
{


public Long unmarshal(String value) {
    return your_util_class.parseLong(value);
}

public String marshal(Long value) {
    return your_util_class.print(value);
}

}

In this way, since you specified adapter classes explicitely, jaxb won't generate default adapters with the default package name org.w3._2001.xmlschema.

It is very important to avoid to use the default package name org.w3._2001.xmlschema. Taking one example, if you have one project A and one project B, and both of them have some schema and bindings. In the old way, both of them generate adapters with exactly the same full qualified names, e.g. org.w3._2001.xmlschema.Adapter1. However, this adapter might be for Long in project A and for Integer in project B. Then, let's say you have a downstream project C using both A and B. Now the problem gets nasty. If C needs to use Adapter1, you cannot predict the used one is from A for Long or from B for Integer. Then, your application C might work fine in some time but maybe fail in a strange way in some other situations. If this happens, the type exception would be like:

org.w3._2001.xmlschema.Adapter1 is not applicable to the field type java.lang.Double...

The solution mentioned by Roy Truelove seems not working when I tried it in my environment with maven-jaxb2-plugin even if the theory is correct.

时光沙漏 2024-10-30 13:40:30

此处创建 org.w3._2001.xmlschema 包是因为 XJC 必须生成一个扩展 javax.xml.bind.annotation.adapters.XmlAdapter 的类,而该类又扩展了调用您的解析/打印静态方法。由于某种原因,它将它们放入这个包中,而不是放在更有用的地方。

您还没有说明您使用哪个 JAXB 实现,但 JAXB RI 对 javaType 绑定自定义进行了扩展,它允许您直接指定 XmlAdapter 的子类,而不是直接指定 XmlAdapter 的子类。 parseMethod/printMethod 对。这样就无需生成合成的 XmlAdapter 桥接类。有关如何执行此操作的信息,请参阅 RI 文档

我想 EclipseLink/Moxy 有类似的东西,但我不确定 Java6 附带的 XJC 是否有能力(Sun 在将其引入 JRE 时似乎已经从 RI 中删除了一半有用的东西) 。

The org.w3._2001.xmlschema package is created here because XJC has to generate a class that extends javax.xml.bind.annotation.adapters.XmlAdapter, which in turn calls your parse/print static methods. For some reason, it puts them into this package, rather than somewhere more useful.

You haven't said which JAXB implementation you use, but the JAXB RI has an extension to the javaType binding customization which allows you to specify a subclass of XmlAdapter directly, rather than parseMethod/printMethod pairs. This removes the need to generate the synthetic XmlAdapter bridge class. See the RI docs for how to do this.

I imagine EclipseLink/Moxy has something similar to this, but I'm not sure if the XJC that ships with Java6 is capable of it (Sun seems to have removed half of the useful stuff from the RI when they brought it into the JRE).

渔村楼浪 2024-10-30 13:40:30

我也遇到了这个问题,使用 this< 解决了它/a>.

基本前提是您在 XJC 编译中包含一个包含以下内容的架构:

<schema xmlns="http://www.w3.org/2001/XMLSchema"
  targetNamespace="http://www.w3.org/2001/XMLSchema"
  xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
  jaxb:version="2.0">
  <annotation><appinfo>
    <jaxb:schemaBindings>
      <jaxb:package name="org.acme.foo"/>
    </jaxb:schemaBindings>
  </appinfo></annotation>
</schema>

然后将包名称调整为您想要放置生成的适配器的位置。 XJC 将相信此模式是 W3C XML 模式本身的模式集的一部分,并将尊重其中的绑定。

I had this problem as well, solved it using this.

The basic premise is that you include a schema in your XJC compilation with following contents:

<schema xmlns="http://www.w3.org/2001/XMLSchema"
  targetNamespace="http://www.w3.org/2001/XMLSchema"
  xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
  jaxb:version="2.0">
  <annotation><appinfo>
    <jaxb:schemaBindings>
      <jaxb:package name="org.acme.foo"/>
    </jaxb:schemaBindings>
  </appinfo></annotation>
</schema>

You then adjust the package name to where you want the generated adapters to be placed. XJC will believe that this schema is part of the schema set for W3C XML Schema itself and will honour the bindings in it.

他夏了夏天 2024-10-30 13:40:30

使用常见数据类型的内置转换器。

<jxb:javaType name="java.lang.Integer" xmlType="xs:integer"              
parseMethod="javax.xml.bind.DatatypeConverter.parseInt"                  
printMethod="javax.xml.bind.DatatypeConverter.printInt" />

Use the built in converters for common datatypes.

<jxb:javaType name="java.lang.Integer" xmlType="xs:integer"              
parseMethod="javax.xml.bind.DatatypeConverter.parseInt"                  
printMethod="javax.xml.bind.DatatypeConverter.printInt" />
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文