2

我有两个顶级课程,它们按组成共享第三个课程。例子:

@XmlRootElement
@XmlType(namespace = "http://example.com/foo")
public class Foo {
    public Shared shared;
}

@XmlRootElement
@XmlType(namespace = "http://example.com/bar")
public class Bar {
    public Shared shared;
}

public class Shared {
    public String string;
}

这些类中的每一个都分配给不同编译单元(模块)中的不同包。现在,当我在每个顶级类上使用 schemagen 时,我希望 Shared 类具有与顶级类相同的名称空间。所以 Foo 的输出应该是这样的:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xs:schema version="1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema">

  <xs:element name="foo" type="Foo"/>

  <xs:complexType name="Foo">
    <xs:sequence>
      <xs:element name="shared" type="Shared" minOccurs="0"/>
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="Shared">
    <xs:sequence>
      <xs:element name="string" type="xs:string" minOccurs="0"/>
    </xs:sequence>
  </xs:complexType>
</xs:schema>

但是,它不是这样工作的。相反,Shared 类具有默认命名空间,因此我得到两个模式文件,一个用于 Foo 的命名空间,一个用于 Shared 的命名空间。

有没有办法解决这个问题而没有明显的解决方案来复制 Shared 类,从而不再共享它?

4

2 回答 2

1

在调查了问题并详细说明了选项之后,我决定更改设计并为我的所有类使用一个且只有一个命名空间。理由如下:

  1. 类和命名空间之间的关系自然是一对一的。即使我手动模拟 XSD 以便我的实例文档正确验证,JAXB 解组器也会忽略属于不匹配的名称空间的元素,因此破解 XSD 根本没有帮助。

  2. 我可以轻松地在多个包和编译单元上重用相同的命名空间。只需要正确设置类路径,当使用 jaxb2-maven-plugin 时,Maven 将为我做这件事。

  3. 我可以轻松地将我的所有类与一个命名空间相关联,并且每个顶级元素仍然具有不同的 XSD 文件。优点是每个输出 XSD 文件仅包含在运行 schemagen 时从包含的根元素类引用的类(即复杂类型)。

进行此更改后,每个编译单元都有一个 XSD 文件。每个编译单元只包含一个根元素(即类)。每个根元素仅引用通过表示根元素的类可强访问的复杂类型。这正是我想要的。

于 2013-09-22T16:51:44.153 回答
1

如果共享类应该与顶级类具有相同的名称空间,则必须复制它。如果真的要共享,必须在第三个 XSD 中定义,并导入到两个顶级 XSD 中。所以 Foo 的结果应该看起来像:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema version="1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:tns="http://www.example.org/schema/foo"
    xmlns:shared="http://www.example.org/schema/shared"
    targetNamespace="http://www.example.org/schema/foo">

    <xs:import namespace="http://www.example.org/schema/shared" schemaLocation="http://www.example.org/schema/shared/shared.xsd"/>

    <xs:element name="foo" type="Foo"/>

    <xs:complexType name="Foo">
        <xs:sequence>
            <xs:element name="shared" type="shared:Shared" minOccurs="0"/>
        </xs:sequence>
    </xs:complexType>

</xs:schema>

然后可以将 Shared 的 XSD 导入两个顶级 XSD。如果您的 Shared XSD 位于一个单独的项目中,您可能需要一个目录文件来指定其位置:

PUBLIC "http://www.example.org/schema/shared" "../../../../shared/src/main/xsd/shared.xsd"

我总是使用契约优先,即创建 XSD 并让 JAXB 生成类。您正在使用schemagen基于类生成 XSD。以防万一您使用的是jaxb2-maven-plugin我找到了一个听起来像是在做您需要的参数。transformSchemas它允许您指定模式映射并将xs:import语句写入生成的 XSD。我没有尝试过,但我希望它有所帮助。

于 2013-09-22T12:44:17.293 回答