如何解决第三方 XML 架构冲突?
我正在使用第三方编写的一组架构描述符文件。我需要为它们生成 JAXB 存根。每个 XSD 定义了不同的消息类型,以及许多支持的简单和复杂类型。许多类型对于每个 XSD 都是通用的,但作者没有将它们分解到单独的 XSD 中,而是选择在每个命名空间中定义它们。当我尝试使用 xjc 将 XSD 编译到单个包中时,这会产生一系列命名空间冲突。我被迫将它们分成独特的包。问题在于,这使得它们在应该可以互换的情况下不可互换。我必须进行大量额外的转换才能在不同的消息类型中使用一种消息类型的数据。
我的问题:是否有某种方法(绑定自定义?)我可以指示 xjc 对每种共享类型使用一个 java 类,而不是分布在不同包中的唯一类?
这是一个简化的示例。我有两个 XSD,一个用于插入消息,另一个用于响应消息。该响应旨在引用插入消息。
<!-- insert.xsd -->
<xs:schema
xmlns="msg.insert"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="msg.insert">
<xs:element name="Message" type="Message" />
<xs:complexType name="Message">
<xs:sequence>
<xs:element
maxOccurs="1"
minOccurs="1"
name="MessageId"
type="Identifier" />
<xs:element
maxOccurs="1"
minOccurs="1"
name="SequenceId"
type="Identifier" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="Identifier">
<xs:sequence>
<xs:element
maxOccurs="1"
minOccurs="1"
name="ID"
type="xs:string" />
<xs:element
maxOccurs="1"
minOccurs="1"
name="Created"
type="xs:dateTime" />
</xs:sequence>
</xs:complexType>
</xs:schema>
这是第二个 XSD...
<!-- response.xsd -->
<xs:schema
xmlns="msg.response"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="msg.response">
<xs:element name="Message" type="Message" />
<xs:complexType name="Message">
<xs:sequence>
<xs:element
maxOccurs="1"
minOccurs="1"
name="MessageId"
type="Identifier" />
<xs:element
maxOccurs="1"
minOccurs="1"
name="SequenceId"
type="Identifier" />
<xs:element
maxOccurs="1"
minOccurs="1"
name="ReferenceId"
type="Identifier" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="Identifier">
<xs:sequence>
<xs:element
maxOccurs="1"
minOccurs="1"
name="ID"
type="xs:string" />
<xs:element
maxOccurs="1"
minOccurs="1"
name="Created"
type="xs:dateTime" />
</xs:sequence>
</xs:complexType>
请注意,两个架构中的Identifier
复杂类型是相同的。它可以而且应该在消息类型之间互换。但是当我运行 xjc 时...
xjc -d java -p example.msg insert.xsd response.xsd
...我在 Message、Identifier 和 ObjectFactory 类上遇到冲突,如下所示。
[ERROR] A class/interface with the same name "example.msg.Message" is already in use. Use a class customization to resolve this conflict.
line 8 of insert.xsd
[ERROR] (Relevant to above error) another "Message" is generated from here.
line 8 of response.xsd
[ERROR] A class/interface with the same name "example.msg.Identifier" is already in use. Use a class customization to resolve this conflict.
line 15 of insert.xsd
[ERROR] (Relevant to above error) another "Identifier" is generated from here.
line 16 of response.xsd
[ERROR] Two declarations cause a collision in the ObjectFactory class.
line 8 of insert.xsd
[ERROR] (Related to above error) This is the other declaration.
line 8 of response.xsd
我完全理解为什么 xjc 会抱怨,我正在尝试找到一种方法来哄骗 xjc 使用 Identifier 类型的公共类,并解决 ObjectFactory 类中的冲突。一种解决方案是将常见类型分解到单独的命名空间中,并从每种消息类型的 XSD 中引用它们,但正如前面提到的,这些都是由第三方编写的,我无法更改它们。
现在我将每个 XSD 编译成一个单独的 java 包。这可行,但是非常非常麻烦。
错误输出表明有一种方法可以通过绑定自定义来做到这一点,但到目前为止我还没有弄清楚如何实现这一点。有人能指出我正确的方向吗?
I'm working with a set of schema descriptor files written by a third party. I need to generate JAXB stubs for them. Each XSD defines a different message type, along with a number of supporting simple and complex types. Many of the types are common to each XSD, but rather than factor them out into a separate XSD, the authors chose to define them in each namespace. This creates a grundle of namespace collisions when I try to compile the XSD's using xjc into a single package. I'm forced to separate them into unique packages. The problem is that this makes them non-interchangeable, when they should be. I have to do a lot of extra conversion to use data from one message type in a different message type.
My question: is there some way (binding customization?) I can instruct xjc to use one java class for each shared type, rather than unique classes spread across different packages?
Here's a simplified example. I've got two XSD's, one for an insert message and another for a response message. The response is meant to reference an insert message.
<!-- insert.xsd -->
<xs:schema
xmlns="msg.insert"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="msg.insert">
<xs:element name="Message" type="Message" />
<xs:complexType name="Message">
<xs:sequence>
<xs:element
maxOccurs="1"
minOccurs="1"
name="MessageId"
type="Identifier" />
<xs:element
maxOccurs="1"
minOccurs="1"
name="SequenceId"
type="Identifier" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="Identifier">
<xs:sequence>
<xs:element
maxOccurs="1"
minOccurs="1"
name="ID"
type="xs:string" />
<xs:element
maxOccurs="1"
minOccurs="1"
name="Created"
type="xs:dateTime" />
</xs:sequence>
</xs:complexType>
</xs:schema>
Here's the second XSD...
<!-- response.xsd -->
<xs:schema
xmlns="msg.response"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="msg.response">
<xs:element name="Message" type="Message" />
<xs:complexType name="Message">
<xs:sequence>
<xs:element
maxOccurs="1"
minOccurs="1"
name="MessageId"
type="Identifier" />
<xs:element
maxOccurs="1"
minOccurs="1"
name="SequenceId"
type="Identifier" />
<xs:element
maxOccurs="1"
minOccurs="1"
name="ReferenceId"
type="Identifier" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="Identifier">
<xs:sequence>
<xs:element
maxOccurs="1"
minOccurs="1"
name="ID"
type="xs:string" />
<xs:element
maxOccurs="1"
minOccurs="1"
name="Created"
type="xs:dateTime" />
</xs:sequence>
</xs:complexType>
Note the Identifier
complex type is identical in both schemas. It can and should be interchangeable between message types. But when I run xjc thus...
xjc -d java -p example.msg insert.xsd response.xsd
...I get collisions on the Message, Identifier, and ObjectFactory classes as follows.
[ERROR] A class/interface with the same name "example.msg.Message" is already in use. Use a class customization to resolve this conflict.
line 8 of insert.xsd
[ERROR] (Relevant to above error) another "Message" is generated from here.
line 8 of response.xsd
[ERROR] A class/interface with the same name "example.msg.Identifier" is already in use. Use a class customization to resolve this conflict.
line 15 of insert.xsd
[ERROR] (Relevant to above error) another "Identifier" is generated from here.
line 16 of response.xsd
[ERROR] Two declarations cause a collision in the ObjectFactory class.
line 8 of insert.xsd
[ERROR] (Related to above error) This is the other declaration.
line 8 of response.xsd
I completely understand why xjc is complaining, I'm trying to find a way to coax xjc into using a common class for the Identifier type, as well as resolve the collisions in the ObjectFactory class. One solution would be to factor the common types out into a separate namespace and reference them from each message type's XSD, but as mentioned these are all written by a third party and I don't have the ability to change them.
For now I'm compiling each XSD into a separate java package. This works but is very, very cumbersome.
The error output suggests there's a way to do this with a binding customization, but so far I haven't figured out how to make that work. Can anyone point me in the right direction?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您只需在 wsimport 命令中添加以下自定义参数即可解决此问题:
这样,解析 xml 时将自动删除任何名称冲突。
希望这有帮助
you can solve this problem just by adding the following custom arg in the wsimport command:
This way, any name conflict will be automatically removed when parsing the xml.
Hope this helps
我必须处理类似的问题来编译一个巨大的 XSD 库(>1.8K XSD 文件),并且 XSD 之间存在大量重复类型。
我发现的唯一可行的解决方案是生成一个中间模型,其中每个命名空间都有默认包,然后使用 Java 代码模型将所有类型类移动到单个包中,折叠重复的类。
最后,我必须破解封送处理以避免折叠类中的名称空间感知。
这似乎是一个疯狂的解决方案,但效果很好。
BTW -XautoNameResolution 只是自动重命名重复类型类的一种方法,但它并不能解决重复问题。
I had to deal with a similar issue to compile a huge library of XSD ( >1.8K XSD files) with a large rate of duplicated types between the XSDs.
The only feasible solution I've found was to generate an intermediate model with default packages per namespace, and process that afterward with Java codemodel moving all type classes into a single package, collapsing the duplicated classes.
Finally, I had to hack the marshaling to avoid namespace aware in the collapsed classes.
It seems like a crazy solution but worked just fine.
BTW -XautoNameResolution is just a way to automatically rename the duplicated type classes, but it does not solve the duplication issue.