【问题标题】:jaxb override package of a specific generated set of classes特定生成的一组类的 jaxb 覆盖包
【发布时间】:2012-01-12 16:05:20
【问题描述】:

我有一个大型第三方 xsd 文件,它通过导入引入一大堆其他 xsd 文件。整个事情产生了1000多个类。当我告诉 xjc (jaxb) 处理器生成特定包中的所有内容时,我会遇到各种命名冲突。如果我不指定包,那么处理器会使用 xsd 文件中的目标属性创建 java 包,并且整个生成过程不会出现任何错误。

问题在于包结构很糟糕,因为目标名称选择得非常糟糕。其他开发人员讨厌它。他们只需要几节课。

所以我一直在尝试做的是给处理器一个 bindings.xml 文件,我想在其中指定要在给定包名称中生成的某些类。 我在 Oracle 网站、论坛和示例的文档之间来回切换。我不能引用绑定文件的每一次迭代。我现在的化身是这样的:

<jaxb:bindings 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
    version="2.1"
    schemaLocation="heavy.xsd"
    node="//xsd:element[@name='Error']"
>

    <jaxb:bindings node="//xsd:element[@name='Error']">
        <jaxb:package name="ABC"/>
    </jaxb:bindings>

    <jaxb:globalBindings
        underscoreBinding="asCharInWord"
        localScoping="toplevel"
        typesafeEnumMaxMembers="10000"
        generateElementClass="true"
    >
    </jaxb:globalBindings>


<!--
        <jaxb:package name="ABC"/>
-->

<!--
    <jaxb:schemaBindings>
        <jaxb:package name="ABC"/>
    </jaxb:schemaBindings>
-->

<!--
    <jaxb:schemaBindings>
        <jaxb:package name="ABC"/>
        <jaxb:nameXmlTransform>
            <jaxb:elementName prefix="Error"/>
        </jaxb:nameXmlTransform>
    </jaxb:schemaBindings>
-->

</jaxb:bindings>

无论我尝试什么,我还没有看到它在 ABC 包中生成任何类。在这种情况下,我希望在 ABC 中生成错误。任何帮助将不胜感激。

【问题讨论】:

  • 如果您找到任何方法可以做到这一点,我对您的解决方案很感兴趣。

标签: java xsd jaxb


【解决方案1】:

很遗憾,您无法按照自己的意愿行事。我想要同样的东西,我在同一条船上。但直接来自神谕:

http://docs.oracle.com/cd/E19316-01/819-3669/bnbbt/index.html

相关信息:

name - 是派生 Java 接口的名称。它必须是合法的 Java 接口名称,并且不能包含包前缀。包前缀继承自包的当前值。

因此,元素根本无法指定其每个 xsd 继承的不同包。

【讨论】:

    【解决方案2】:

    我会这样做的方式更像这样:

    <?xml version="1.0" encoding="utf-8"?>
    <jxb:bindings xmlns:jxb="http://java.sun.com/xml/ns/jaxb" xmlns:xs="http://www.w3.org/2001/XMLSchema" version="2.1" jxb:extensionBindingPrefixes="xjc">
        <jxb:bindings schemaLocation="XSD1.xsd" node="/xs:schema">
            <jxb:globalBindings>
                <!-- -->
            </jxb:globalBindings>
            <jxb:schemaBindings xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc">
                <jxb:package name="com.something">
                </jxb:package>
            </jxb:schemaBindings>
            <jxb:bindings node="//xs:element[@name='Error']">
                <jxb:class xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" name="MyError"/>
                <jxb:property xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" name="Whatever"/>
            </jxb:bindings>
        </jxb:bindings>
        <jxb:bindings schemaLocation="XSD2.xsd" node="/xs:schema">
            <jxb:schemaBindings xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc">
                <jxb:package name="com.somethingelse">
                </jxb:package>
            </jxb:schemaBindings>
        </jxb:bindings>
    </jxb:bindings>
    

    【讨论】:

    • 为什么要跨 XML 复制 xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"?放到根元素不是更容易吗?
    • sn-p 来自工具自动生成的绑定文件,因此对 XML 命名空间的“次优”使用。
    • 如果我正确理解了这个绑定文件,它会告诉所有从 XSD1.xsd 生成的 java 文件都在 com.something 包中,将 Error 类重命名为 MyError,并且所有生成的 java 文件都来自com.somethingelse 包中的 XSD2.xsd。那是对的吗?但是我正在尝试解决的问题是如何将一个特定元素放入特定包中,而所有其他元素都放入它们的正常包名称中。我需要覆盖一个特定的元素。
    • 是的,你的理解是正确的。我不知道控制单个类的包名称的方法。如果我必须这样做,我会在你的情况下做什么(免责声明:我在这里使用的工具有偏见)将隔离我想要在特定java中的任何内容包,在一个单独的 XSD 文件中 - 实际上引入一个或多个 s。这样,如果你需要让它工作,它就会工作。此外,在此过程中,我使用的同一工具将能够删除任何未使用的 XSD 内容(由您的实现限定),从而减少类
    • 不是每个人都可以控制 XSD。如果你解析它们,它们将来可能会改变。我正在寻找相同的答案。
    【解决方案3】:

    这里是一个 bindings.xjb 文件的示例,其中 java 源是在primer.myPo 包中生成的。

    <jxb:bindings version="1.0"
                   xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
                   xmlns:xs="http://www.w3.org/2001/XMLSchema">
      <jxb:bindings schemaLocation="po.xsd" node="/xs:schema">
        <jxb:globalBindings
             fixedAttributeAsConstantProperty="false"
             collectionType="java.util.Vector"
             typesafeEnumBase="xs:NCName"
             choiceContentProperty="false"
             typesafeEnumMemberName="generateError"
             enableFailFastCheck="false"   
             generateIsSetMethod="false"
             underscoreBinding="asCharInWord"/>
        <jxb:schemaBindings>
          <jxb:package name="primer.myPo">
            <jxb:javadoc><![CDATA[<body>Package level documentation for generated package primer.myPo.</body>]]>
    </jxb:javadoc>
          </jxb:package>
          <jxb:nameXmlTransform>
            <jxb:elementName suffix="Element"/>
          </jxb:nameXmlTransform>
        </jxb:schemaBindings>
    
        <jxb:bindings node="//xs:complexType[@name='PurchaseOrderType']">
          <jxb:class name="POType">
            <jxb:javadoc>A &lt;b>Purchase Order&lt;/b> consists of addresses and items.</jxb:javadoc>
          </jxb:class>
        </jxb:bindings>
    
        <jxb:bindings node="//xs:complexType[@name='USAddress']">
          <jxb:class>
            <jxb:javadoc><![CDATA[First line of documentation for a <b>USAddress</b>.]]></jxb:javadoc>
          </jxb:class>
    
          <jxb:bindings node=".//xs:element[@name='name']">
            <jxb:property name="toName"/>
          </jxb:bindings>
    
          <jxb:bindings node=".//xs:element[@name='zip']">
             <jxb:property name="zipCode"/>
          </jxb:bindings>
        </jxb:bindings> <!-- node="//xs:complexType[@name='USAddress']" -->
    
        <jxb:bindings node="//xs:complexType[@name='Items']">
          <jxb:bindings node=".//xs:element[@name='item']//xs:element[@name='quantity']">
            <jxb:property generateIsSetMethod="true"/>
    
            <jxb:bindings node="./xs:simpleType">
              <jxb:javaType name="short" 
                            parseMethod="javax.xml.bind.DatatypeConverter.parseShort" 
                            printMethod="javax.xml.bind.DatatypeConverter.printShort" />
            </jxb:bindings>
          </jxb:bindings>  <!--  node="//xs:complexType[@name='Items']" -->
    
          <jxb:bindings node=".//xs:element[@name='USPrice']">
            <jxb:property name="Price"/>
          </jxb:bindings>
    
          <jxb:bindings node=".//xs:attribute[@name='partNum']">
            <jxb:property name="partNumber"/>
          </jxb:bindings>
        </jxb:bindings>
    
        <jxb:bindings node="//xs:simpleType[@name='USState']">
          <jxb:typesafeEnumClass/>
        </jxb:bindings>
    
        <jxb:bindings node="//xs:simpleType[@name='ZipCodeType']">
          <jxb:javaType name="int"     
                        parseMethod="javax.xml.bind.DatatypeConverter.parseInt" 
                        printMethod="javax.xml.bind.DatatypeConverter.printInt"/>
        </jxb:bindings>
      </jxb:bindings> <!-- schemaLocation="po.xsd" node="/xs:schema" -->
    
    </jxb:bindings>
    

    【讨论】:

    • 我认为这会使 po.xsd 在primer.myPro 包中为任何以元素名称结尾的元素生成内容?其次,它将类从名为 PurchaseOrderType 的 complexType 重命名为 POType 作为其新类名。我还发现了如何重命名特定类。如果只有一种方法可以将该类放入特定的包中,这就是我所追求的。我没有得到剩余的部分。它是根据 xpath 匹配的元素、属性和 simpleTypes 设置属性吗?但是然后呢?
    • 这不是他问题的答案。他想将一个特定元素映射到不同的包而不是 xsd。
    猜你喜欢
    • 2012-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多