我有一个XSD,它不是自己创建的,而是从另一方收到的.所以我不能改变这个XSD,因为我必须确保与另一方的兼容性.
使用简单绑定模式使用XJC 2.2和JAXB 2.2我想在一个空的hello元素内部创建一个根元素.但是当编组时我得到了很多额外的命名空间废话.哪个对我来说看起来不需要.(它虽然有效,但发送的数据更多......)
XSD Rootelement:
<element name="epp">
<complexType>
<choice>
<element name="greeting" type="epp:greetingType" />
<element name="hello" />
<element name="command" type="epp:commandType" />
<element name="response" type="epp:responseType" />
<element name="extension" type="epp:extAnyType" />
</choice>
</complexType>
</element>
Run Code Online (Sandbox Code Playgroud)
Java代码:
Epp epp = new Epp();
epp.setHello("");
Run Code Online (Sandbox Code Playgroud)
编组结果:
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
<hello xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" xsi:type="xs:string"></hello>
</epp>
Run Code Online (Sandbox Code Playgroud)
首选结果:
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
<hello />
</epp>
Run Code Online (Sandbox Code Playgroud)
要么:
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
<hello></hello>
</epp>
Run Code Online (Sandbox Code Playgroud)
有没有办法使这成为可能,最好不更改XSD或手动更改XJC编译的类?
问题如下:架构没有定义 element 的类型hello
。结果,XJC 生成一个类型为 的字段Object
。这意味着 JAXB 必须在编组期间检测我们正在处理的对象类型。我不确定细节,但我想它会检查运行时类型,然后进行相应的处理。因为String
- 这是您实际放入该hello
字段的内容 - 直接绑定到模式类型(即xs:string
),JAXB 将随之而来。到目前为止,一切都很好。
但 JAXB 正在尝试生成对于解组也有用的 XML。由于模式没有指定类型并且hello
字段是一个对象,因此尝试从 XML 解组将使 JAXB 猜测它实际上应该将内容转换成什么。告诉它如何操作的一种方法是使用属性在 XML 元素中指定类型xsi:type
。该属性属于xsi
-bound 命名空间,因此必须声明并绑定该前缀。这就是 发生的情况xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
。但这还不是全部...声明xsi:type
使用了 XML 模式命名空间中的类型,绑定到前缀xs
,这意味着也必须声明它!因此xmlns:xs="http://www.w3.org/2001/XMLSchema"
。
结果是:一堆混乱的名称空间声明,只是为了告诉使用 XML 的人它实际上包含一个字符串。这可以通过添加 string 作为架构中 hello 元素的类型来解决,但这不是您的选择。
幸运的是,你还没有完全走运。您可以使用外部绑定文件自定义绑定。详细信息可以在这里找到:http://download.oracle.com/docs/cd/E17802_01/webservices/webservices/docs/2.0/tutorial/doc/JAXBUsing4.html
通常,这个绑定文件应该可以解决问题:
<?xml version="1.0" encoding="UTF-8"?>
<bindings xmlns="http://java.sun.com/xml/ns/jaxb"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/jaxb http://java.sun.com/xml/ns/jaxb/bindingschema_2_0.xsd"
version="2.1">
<!-- Bindings for the general schema -->
<bindings schemaLocation="test.xsd" node="/xs:schema">
<bindings node="xs:element[@name='epp']">
<bindings node=".//xs:element[@name='hello']">
<javaType name="java.lang.String" />
</bindings>
</bindings>
</bindings>
</bindings>
Run Code Online (Sandbox Code Playgroud)
...但是当我尝试使用 xjc 时,我收到了错误the compiler was unable to honor this javaType customization
。当我在模式中的 hello 元素上指定一些标准模式类型(如 string 或 int)时,它确实有效,但当我实际尝试为转换提供解析和打印方法时,它再次不起作用,所以我要假设这是 xjc 中的错误,当架构中未指定类型时会发生该错误。
我希望其他人可以就绑定问题提供建议。否则,我看到的唯一选择是通过一些 XSLT 转换发送您的模式,然后在其上释放 XJC 以将每个非类型化元素默认设置为字符串。