6

我正在开发一个使用 XJC 从 XSD 生成 Java POJO 的应用程序。有几十种模式,而且这个数字还会增长。应用程序还需要能够处理同一模式的不同版本,这意味着我将有多个定义通用类型的模式。我正在尝试自定义绑定,以便某些核心类型实现通用接口。JAXB2 Basics 的继承插件似乎可以满足我的需要,但我似乎无法确定正确的语法。

这是我的架构的相关部分:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
           xmlns:my="http://example.com/core"
           targetNamespace="http://example.com/core"
           xmlns:xml="http://www.w3.org/XML/1998/namespace">

    ...

    <xs:complexType name="addressType">
        <xs:sequence>
            <xs:element name="Address" type="xs:string"/>
            <xs:element name="City" type="xs:string"/>
            <xs:element name="Province" type="xs:string"/>
            <xs:element name="Country" type="xs:string"/>
            <xs:element name="County" type="xs:string" minOccurs="0"/>
            <xs:element name="PostalCode" type="xs:string"/>
        </xs:sequence>
    </xs:complexType>

    ...

</xs:schema>

...这就是我的自定义绑定文件的样子:

    <?xml version="1.0"?>
<jaxb:bindings 
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
    xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
    xmlns:inheritance="http://jaxb2-commons.dev.java.net/basic/inheritance"
    xmlns:my="http://example.com/core"
    jaxb:extensionBindingPrefixes="inheritance"
    version="2.1">

    <jaxb:bindings scd="x-schema::my" xmlns:my="http://example.com/core">
        <jaxb:globalBindings localScoping="toplevel">
            <jaxb:serializable/>
            <xjc:simple/>
        </jaxb:globalBindings>
        <jaxb:bindings scd="/type::my:addressType">
            <inheritance:implements>com.mysite.validator.ValidatableAddress</inheritance:implements> 
            <!--<xjc:superInterface name="com.mysite.validator.ValidatableAddress"/>-->
        </jaxb:bindings>
    </jaxb:bindings>

</jaxb:bindings>

我使用的是scd方法,因为在所有展示如何使用继承插件的“传统”绑定示例中,都指定了schemaLocation。我想避免因为我们的大量(并且不断增长的)模式而必须指定schemaLocation 。我不想每次添加新模式时都必须更改绑定文件。所以,scd似乎可以满足这个要求。

但是,当我使用上述绑定运行构建时,我得到了这个:

  [xjc] [ERROR] cvc-elt.1: Cannot find the declaration of element 'inheritance:implements'.
  [xjc]   line 18 of file:/dev/workspace/my_app/etc/schemas/bindings-common.xml
  [xjc] failure in the XJC task. Use the Ant -verbose switch for more details
  [xjc] classLoader = java.net.URLClassLoader@ebcdbb
  [xjc] SharedSecrets.getJavaNetAccess()=java.net.URLClassLoader$7@14562c5

如果我注释掉继承:实现行并取消注释xjc:superInterface行,错误就会消失并且构建成功完成,但是我的AddressType类没有实现 ValidatableAddress 类型。

继承插件可以与scd一起使用吗?xjc:superInterface 可以仅限于某些元素吗?

干杯。

4

2 回答 2

4

的作者在这里。

请参阅XJC 中的此问题。简而言之,XJC 出于某种原因不允许 SCD 绑定中的自定义/供应商自定义元素。
inheritance:implements就是这样的定制元素。

所以不,由于 XJC 中的问题,这不起作用。

我个人通过和 XPath 绑定schemaLocation,但使用“虚拟”模式位置 URI 并通过目录重写它。

SCD 本来是一个更好的选择(您绝对正确),但它不起作用。

更新虚拟模式位置和目录。

这是一个自定义一些复杂类型的绑定示例:

<jaxb:bindings 
    schemaLocation="http://schemas.opengis.net/wps/2.0/wpsCommon.xsd" 
    node="/xs:schema">
    <jaxb:bindings node="xs:element[@name='Data']/xs:complexType">
        <wildcard:lax/>
    </jaxb:bindings>
</jaxb:bindings>

它通过schemaLocation和 XPath 绑定。这schemaLocation是一个现有的 URL,但在构建中它通过目录重写到 Maven 工件内的资源中:

REWRITE_SYSTEM "http://schemas.opengis.net" "maven:org.jvnet.ogc:ogc-schemas:jar::!/ogc"

所以基本上http://schemas.opengis.net/wps/2.0/wpsCommon.xsd会从ogc-schema.jar!/ogc/wps/2.0/wpsCommon.xsd.

使用您也可以参考 Maven 工件中的绑定文件

                    <binding>
                        <dependencyResource>
                            <groupId>${project.groupId}</groupId>
                            <artifactId>ows-v_2_0</artifactId>
                            <resource>ows-v_2_0.jsonix.xjb</resource>
                            <version>${project.version}</version>
                        </dependencyResource>
                    </binding>

因此,结合起来,它允许编写一次绑定文件并跨模块重用它们。

但这一切都是一个巨大的痛苦。我是为ogc-schemas项目做的,该项目现在有大约 50 个高度互连的模式。我深受 XJC 缺点和问题的困扰,但这是目前最好的。我什至考虑过分叉和修补 XJC,但这远远超出了我所能承受的努力范围。

所以我最终找到了一些思维导图的变通方法,它们最终以某种方式完成了这项工作。

于 2015-06-16T19:04:42.643 回答
4

感谢 lexcore 的及时和详细的回答。但是这种方法对我不起作用,所以我最终得到了以下解决方案......

因为我使用 Ant 来调用 XJC,所以我最终利用 Ant 的<copy filtering="true"...>功能来动态生成绑定文件。

这是我的绑定“模板”文件(bindings-common.xml):

<?xml version="1.0"?>
<jaxb:bindings 
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
    xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
    xmlns:inheritance="http://jaxb2-commons.dev.java.net/basic/inheritance"
    xmlns:my="http://http://example.com/core"
    jaxb:extensionBindingPrefixes="inheritance" 
    version="2.1">
    <jaxb:bindings>
        <jaxb:globalBindings localScoping="toplevel">
            <jaxb:serializable/>
            <xjc:simple/>
        </jaxb:globalBindings>
    </jaxb:bindings>

    <jaxb:bindings
        schemaLocation="@bindingSchema@" 
        node="/xs:schema">

        <jaxb:bindings node="//xs:complexType[@name='addressType']">
            <inheritance:implements>com.example.validator.ValidatableAddress</inheritance:implements>
        </jaxb:bindings>
    </jaxb:bindings>

</jaxb:bindings>

注意这一行:

<jaxb:bindings
            schemaLocation="@bindingSchema@" 
            node="/xs:schema">

Ant 将为我正在处理的每个模式填充此变量:

<property name="jaxb.binding.template" value="../etc/form-schemas/bindings-common.xml"/>
<property name="jaxb.binding.file" value="${jaxb.src.dir}/bindings-common${schema.version}.xml"/>

<echo message="Filtering ${jaxb.binding.file} using template ${jaxb.binding.template}"/>

<copy file="${jaxb.binding.template}" 
      tofile="${jaxb.binding.file}"
      filtering="true">

    <filterset>
        <filter token="bindingSchema" value="../../etc/form-schemas/${schema.version}/common.xsd"/>
    </filterset>
</copy>

<xjc destdir="${jaxb.src.dir}" 
        extension="true" 
        schema="${schema.file}" 
        package="${package}" 
        binding="${jaxb.binding.file}">

    <arg value="-episode"/> 
    <arg value="${jaxb.src.dir}/common${schema.version}.episode"/> 
    <arg line="-Xinheritance"/>

        <!-- Plugins -->
        <classpath>
            <fileset dir="../build-libs/">
                <!-- JAXB2 Basics library -->
                <include name="jaxb2-basics-0.6.4.jar"/>
                <!-- JAXB2 Basics library dependencies -->
                <include name="jaxb2-basics-runtime-0.6.4.jar"/>
                <include name="jaxb2-basics-tools-0.6.4.jar"/>
                <include name="javaparser-1.0.8.jar"/>
                <include name="commons-beanutils-*.jar"/>
                <include name="commons-lang-*.jar"/>
                <include name="commons-logging-*.jar"/>
            </fileset>
        </classpath>
    </xjc>
</target>

希望这将有助于未来几代的 JAXB 受害者。

于 2015-06-18T14:40:06.087 回答