如何解决第三方XML架构冲突?

时间:2011-10-21 23:10:59

标签: java xml jaxb xsd xjc

我正在处理由第三方编写的一组架构描述符文件。我需要为它们生成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使用标识符类型的公共类,以及解决ObjectFactory类中的冲突。一种解决方案是将常见类型分解为一个单独的命名空间,并从每个消息类型的XSD引用它们,但如上所述,这些都是由第三方编写的,我无法更改它们。

现在我正在将每个XSD编译成一个单独的java包。这有效但非常非常麻烦。

错误输出表明有一种方法可以通过绑定自定义来实现,但到目前为止,我还没有想出如何使其工作。有人能指出我正确的方向吗?

2 个答案:

答案 0 :(得分:2)

只需在 wsimport 命令中添加以下自定义arg即可解决此问题:

-B-XautoNameResolution (without spaces)

这样,解析xml时会自动删除任何名称冲突。

希望这有帮助

答案 1 :(得分:0)

我不得不处理一个类似的问题来编译一个巨大的XSD库(&gt; 1.8K XSD文件),在XSD之间有大量的重复类型。

我发现唯一可行的解​​决方案是生成一个每个命名空间都带有默认包的中间模型,然后使用Java代码模型将所有类型类移动到一个包中,然后折叠重复的类。

最后,我不得不破解编组以避免崩溃类中的名称空间感知。

这似乎是一个疯狂的解决方案,但工作得很好。

BTW -XautoNameResolution只是一种自动重命名重复类型类的方法,但它不能解决重复问题。