java - 使用导入的 XSD 和绑定(bind)生成 JAXB 类

标签 java xml binding xsd jaxb

我正在尝试从导入 x.xsdy.xsdcommon.xsd 生成类。

common.xsd如下:

<?xml version="1.0"?>
    <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xs:import namespace="mynamespace:x" schemaLocation="x.xsd"/>
    <xs:import namespace="mynamespace:y" schemaLocation="y.xsd"/>
</xs:schema>

我尝试使用一个绑定(bind)文件,该文件指定一个由生成的类实现的公共(public)接口(interface)。我的绑定(bind)文件如下:

jaxb:extensionBindingPrefixes="inheritance" version="2.1">

<jaxb:globalBindings> 
    <jaxb:javaType name="java.lang.Long" xmlType="xsd:integer"/> 
</jaxb:globalBindings>

<jaxb:bindings schemaLocation="common.xsd" node="/xsd:schema">

    <jaxb:bindings node="xsd:complexType[@name='Customer']">
        <inheritance:implements>jaxb.BaseMessage</inheritance:implements>
        <jaxb:class />
    </jaxb:bindings>

    <jaxb:bindings node="xsd:complexType[@name='Payments']">
        <inheritance:implements>jaxb.BaseMessage</inheritance:implements>
        <jaxb:class />
    </jaxb:bindings>

我试图生成代码,但它提示说:

[ERROR] XPath evaluation of "xsd:complexType[@name='Customer']" results in empty target node
[ERROR] XPath evaluation of "xsd:complexType[@name='Payments']" results in empty target node

我如何定义绑定(bind)文件中的节点实际上是在单独的外部 XSD 文件中而不是在 common.xsd 中?

最佳答案

通常,您想要执行此操作的方式是使用 Schema Component Designators (SCD)而不是 XPath。

Using SCD for customizations

[XPath] is also error prone, because it relies on the way schema documents are laid out, because the schemaLocation attribute needs to point to the right schema document file. When a schema is split into multiple files for modularity (happens especially often with large schemas), then you'd have to find which schema file it is. Even though you can use relative paths, this hard-coding of path information makes it hard to pass around the binding file to other people.

SCD Support

Compared to the standard XPath based approach, SCD allows more robust and concise way of identifying a target of a customization. For more about SCD, refer to the scd example. Note that SCD is a W3C working draft, and may change in the future.

不幸的是,由于 bug in XJC , SCD 不能与供应商扩充结合使用。您会看到如下错误:

[ERROR] cvc-elt.1: Cannot find the declaration of element 'inheritance:implements'.

author of jaxb2-basics最近写了一个detailed explanation那个特定的问题。基本上,如果您想使用供应商扩展,您现在只能使用 XPath(及其限制)。

基于 XPath 的解决方案

这是一个完整的工作示例,它根据您在问题中提供的信息将 XPath 与供应商扩展一起使用。我相信从导入的模式生成类的正确方法是通过一个单独的绑定(bind)元素。作为这按预期工作的证明,从该绑定(bind) (Cust) 生成的类是可见的,并且由 common.xsd 生成的那些类重用。每个生成的类都实现基类 jaxb.BaseMessage

我相信在修复 XJC 错误之前,这是您会找到的最好的解决方案。

src/main/resources/bindings.xjb:

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

  <jaxb:globalBindings>
    <jaxb:javaType name="java.lang.Long" xmlType="xsd:integer" />
  </jaxb:globalBindings>

  <jaxb:bindings schemaLocation="schema/x.xsd">
    <jaxb:bindings node="//xsd:complexType[@name='Customer']">
      <jaxb:class name="Cust" />
      <inheritance:implements>jaxb.BaseMessage</inheritance:implements>
    </jaxb:bindings>
  </jaxb:bindings>

  <jaxb:bindings schemaLocation="schema/y.xsd">
    <jaxb:bindings node="//xsd:complexType[@name='Payments']">
      <jaxb:class />
      <inheritance:implements>jaxb.BaseMessage</inheritance:implements>
    </jaxb:bindings>
  </jaxb:bindings>

  <jaxb:bindings schemaLocation="schema/common.xsd">
    <jaxb:bindings node="//xsd:complexType[@name='CustomerPayments']">
      <jaxb:class />
      <inheritance:implements>jaxb.BaseMessage</inheritance:implements>
    </jaxb:bindings>
  </jaxb:bindings>

</jaxb:bindings>

src/main/resources/schema/common.xsd:

<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema version="1.0"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:x="http://test.org/common/x"
    xmlns:y="http://test.org/common/y"
    targetNamespace="http://test.org/common">

  <xsd:import namespace="http://test.org/common/x" schemaLocation="x.xsd" />
  <xsd:import namespace="http://test.org/common/y" schemaLocation="y.xsd" />

  <xsd:complexType name="CustomerPayments">
    <xsd:sequence>
      <xsd:element name="customer" type="x:Customer" />
      <xsd:element name="payments" type="y:Payments" />
    </xsd:sequence>
  </xsd:complexType>

</xsd:schema>

src/main/resources/schema/x.xsd:

<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema version="1.0"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    elementFormDefault="qualified"
    attributeFormDefault="unqualified"
    targetNamespace="http://test.org/common/x">

  <xsd:complexType name="Customer">
    <xsd:sequence>
      <xsd:element name="name" type="xsd:string" />
    </xsd:sequence>
  </xsd:complexType>

</xsd:schema>

src/main/resources/schema/y.xsd:

<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema version="1.0"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    elementFormDefault="qualified"
    attributeFormDefault="unqualified"
    targetNamespace="http://test.org/common/y">

  <xsd:complexType name="Payments">
    <xsd:sequence>
      <xsd:element name="amount" type="xsd:float" />
    </xsd:sequence>
  </xsd:complexType>

</xsd:schema>

build.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE project>
<project name="JAXB XPath Test" default="xjc" basedir=".">

  <property name="build.folder" location="build" />

  <taskdef name="xjc" classname="org.jvnet.jaxb2_commons.xjc.XJC2Task">
    <classpath>
        <fileset dir="${basedir}/lib">
          <include name="jaxb-impl-2.2.6.jar" />
          <include name="jaxb-xjc-2.2.6.jar" />
          <include name="jaxb2-basics-ant-0.9.4.jar" />
          <include name="javaparser-1.0.11.jar" />
          <include name="commons-lang3-3.2.jar" />
        </fileset>
    </classpath>
  </taskdef>

  <target name="xjc" description="Generate the source code.">

    <xjc destdir="${basedir}/src/main/java" extension="true">

      <arg line="
        -Xequals
        -XhashCode
        -XtoString
        -Xcopyable
        -Xmergeable
        -Xinheritance" />

      <binding dir="${basedir}/src/main/resources">
        <include name="**/*.xjb" />
      </binding>

      <schema dir="${basedir}/src/main/resources/schema">
        <include name="**/*.xsd" />
      </schema>

      <classpath>
        <fileset dir="${basedir}/lib">
            <include name="jaxb2-basics-0.9.4.jar"/>
            <include name="jaxb2-basics-runtime-0.9.4.jar"/>
            <include name="jaxb2-basics-tools-0.9.4.jar"/>
            <include name="commons-beanutils-1.8.0.jar"/>
            <include name="commons-lang3-3.2.jar"/>
            <include name="commons-logging-1.1.1.jar"/>
        </fileset>
      </classpath>

    </xjc>

  </target>

</project>

关于java - 使用导入的 XSD 和绑定(bind)生成 JAXB 类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29763259/

相关文章:

javascript - 在新插入的元素上应用 javascript 库

java - 使用 Thread.sleep 了解循环中的 toast

java - GWT CELLTABLE pager 如何确定用户点击了哪个按钮?

java - Log4j2:仅抑制 DEBUG 消息

C# WPF - 字符串(存储在数据库中)从/到 RichTextBox

c# - 从 DataTemplate 绑定(bind) ZIndex

java - Java 中没有显式访问修饰符意味着什么?

java - java中 boolean 表达式如何工作?

c# - 如何在xml注释<code>标签中指定语言

c# - 强制扩展 XDocument 中的空元素