【问题标题】:JAXB use element name instead of type when generating pojoJAXB 在生成 pojo 时使用元素名称而不是类型
【发布时间】:2019-02-02 18:26:37
【问题描述】:

使用 jaxb 我想从 xsd 生成 pojos。 但是 xsd 是由外部供应商提供的,其中元素具有有意义的名称, 但是类型很奇怪。只是一个例子:

<xs:element name="PersonAddress" type="PerAdr" />

<xs:complexType name="PerAdr">
    <xs:sequence>
        <xs:element name="street" type="xs:string" minOccurs="1" maxOccurs="unbounded" />
        <xs:element name="house" type="xs:string" minOccurs="1" maxOccurs="unbounded" />
    </xs:sequence>
</xs:complexType>

所以生成的类叫做 PerAdr。 如何使它生成名称是元素名称的类,而不是类型,以便在这种情况下生成类 PersonAddress。

我有一个巨大的xsd,所以想一个聪明的方法来做,而不仅仅是在.xjb文件中写数百行

【问题讨论】:

    标签: spring xsd jaxb pojo


    【解决方案1】:

    我并不是 JAXB 的专业人士。但我查看了 JAXB 规范(此处:http://download.oracle.com/otn-pub/jcp/jaxb-2.0-fr-oth-JSpec/jaxb-2_0-fr-spec.pdf)并发现以下内容:


    模式派生的Element类的特点是派生在 “元素声明架构组件”的属性条款 第349页如下:

    • 生成的 Java Element 类的 name 派生自 元素声明 {name} 使用 XML 名称到 Java 标识符 类名的映射算法。

    • 每个生成的 Element 类都必须扩展 Java 值类 javax.xml.bind.JAXBElement&lt;T&gt;。下一个项目符号指定 用于泛型参数 T 的架构派生 Java 类名。

    • 如果元素声明的{类型定义}

      • 匿名:第二个项目符号中的通用参数 T 设置为模式派生类,表示按指定生成的匿名类型定义 在第 6.7.3 节中。
      • 命名: 第二个项目符号中的通用参数 T 设置为表示元素声明的 {type definition} 的 Java 类。

    因此,可以由此得出结论:一旦您有了一个具有命名 XSD 类型的 XSD 元素,您就必须处理一个表示该类型并以它命名的 Java 类。这是合乎逻辑的。毕竟,您可能拥有具有相同全局类型的不同 XSD 元素。这是默认映射。

    但是,JAXB 允许自定义(XML 模式),您可以使用这些自定义覆盖某些内容。例如,您可以修改 XSD 类型生成的 Java 类的名称,例如:

    <xs:complexType name="USAddress">
      <xs:annotation> <xs:appinfo>
        <jaxb:class name="MyAddress" />
      </xs:appinfo></xs:annotation>
      <xs:sequence>...</xs:sequence>
      <xs:attribute name="country" type="xs:string"/>
    </xs:complexType>
    

    因此,结果 Java 类将被命名为 MyAddress,而不是 USAddress。这看起来像是解决您的问题的方法,但要利用它,您需要修改 XSD 中的每个类型定义,这听起来令人生畏,因为您的架构很大。

    那么,你能做什么呢?

    首先,您需要确保架构中的每个 XSD 元素及其(全局定义的)类型彼此唯一对应。如果碰巧有几个不同的 XSD 元素具有相同的类型,显然类型名称不能等于所有这些元素。在这种情况下,如果您不喜欢原始类型名称,您只需手动编辑该架构并为这些类型指定不同的名称,因为它更适合您。

    只有当关系 XSD 元素 其 XSD 类型是唯一的时,任何自动化都是可能的!在这种情况下,您可以从元素名称派生类型名称:使其相同或添加例如T 前缀:TPersonAddress

    这通常称为重构,可以自动完成。问题是如何?

    好吧,既然 XSD 是 XML,您可以编写一个 XSLT 脚本 来进行必要的转换。但这可能不是那么简单,因为您将不得不稍微解析模式。也就是说,识别那里的每个 XSD 元素并找到相应的 XSD 类型,然后在两个位置更改类型名称。或者,您可以在每个 XSD 类型的定义中插入这些自定义指令(&lt;jaxb:...&gt; 元素),如上所述。我不知道编写这样的东西需要多少时间。这肯定会归结为创建索引(使用&lt;xsl:key&gt; 构造)并通过它进行迭代。


    或者,我可以向您推荐一些非正统方法。我们开发了一个名为FlexDoc/XML 的工具。本质上,它是将 XML 文件转换成任何东西。转换是使用一些类似于 XSLT 的模板进行编程的。

    最初的想法是将类似 XSLT 的方法扩展到通过各种 API 提供的任何基于 Java 的数据源。例如,我们有一个类似的产品,叫做 FlexDoc/Javadoc 模仿标准 Javadoc。但后来我们意识到,XML 本身也是一个充满各种繁重任务的好领域,而 XSLT 对这些任务来说太轻量级了。例如,通过数百个 XSD 和 WSDL 文件生成易于导航的单个文档,我们现在有两个模板集:XSDDocWSDLDoc。 (我们也在为 JSON Schema 做类似的事情)。

    使用FlexDoc/XML 可以创建一个模板来满足您的需求(重命名那些XSD 类型)。这可以在一个小时内完成,如果您最终购买“FlexDoc/XML SDK”许可证,我们将为您完成。 (人们通常购买 SDK 许可证来自定义 XSDDoc/WSDLDoc 模板。但它同样可以用作像您这样的任务的单独工具。)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-05-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-18
      • 1970-01-01
      相关资源
      最近更新 更多