schemagen:如何共享类,但不共享它们的命名空间



我有两个顶级类,它们通过组合共享第三个类。例:

@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>

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

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

如果共享类应该与顶级类具有相同的命名空间,则必须复制它。如果确实要共享它,则必须在第三个 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>

然后,可以将共享的 XSD 导入到两个顶级 XSD 中。如果共享 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 中。我没有尝试过,但我希望它有所帮助。

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

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

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

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

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

最新更新