我有这样的绑定文件
<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>
Run Code Online (Sandbox Code Playgroud)
模式类在"example"(正确)中生成,但是"org.w3._2001.xmlschema"中的XmlAdapters(错误).我怎样才能解决这个问题?
ska*_*man 11
在org.w3._2001.xmlschema这里创建的包,因为XJC必须产生一个类,它扩展javax.xml.bind.annotation.adapters.XmlAdapter,进而调用您解析/打印静态方法.出于某种原因,它将它们放入这个包中,而不是更有用的地方.
您还没有说过您使用的JAXB实现,但是JAXB RI具有javaType绑定自定义的扩展,它允许您XmlAdapter直接指定子类,而不是parseMethod/ printMethodpairs.这消除了生成合成XmlAdapter桥类的需要.有关如何执行此操作,请参阅RI文档.
我想EclipseLink/Moxy有类似的东西,但是我不确定Java6附带的XJC是否能够实现它(当它们将它带入JRE时,Sun似乎从RI中删除了一半有用的东西) .
Ala*_*ier 10
对于Apache CXF用户,最干净的方法是使用-p提供的选项wsdl2java.
-p [wsdl-namespace =] PackageName
指定要用于生成的代码的零个或多个包名称.(可选)指定包名称映射的WSDL名称空间.
在我们的例子中
-p http://www.w3.org/2001/XMLSchema=org.acme.foo
如果您使用cxf-codegen-plugin,那么只需添加另一对<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>
Run Code Online (Sandbox Code Playgroud)
不需要指向保留的XSD命名空间的targetNamespace,也不需要catch-all jaxb包绑定.
使用GlobalBinding的更好方法是指定显式适配器,而不是使用此解析/打印对。例如,代替以下内容:
<jaxb:javaType name="java.lang.Long" xmlType="xs:long"
parseMethod="com.mypackage.myclass.parseLong"
printMethod="com.mypackage.myclass.print"/>
Run Code Online (Sandbox Code Playgroud)
相反,您应该:
<xjc:javaType name="java.lang.Long" xmlType="xs:long"
adapter="com.mypackage.LongAdapter"/>
Run Code Online (Sandbox Code Playgroud)
记住要为xjc添加名称空间:
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
jxb:extensionBindingPrefixes="xjc"
Run Code Online (Sandbox Code Playgroud)
类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);
}
}
Run Code Online (Sandbox Code Playgroud)
这样,由于您显式指定了适配器类,因此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...
Run Code Online (Sandbox Code Playgroud)
当我在环境中使用maven-jaxb2-plugin尝试该方法时,Roy Truelove提到的解决方案似乎不起作用,即使该理论是正确的。