我有两个顶级类,它们通过组合共享第三个类。例:
@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 中。我没有尝试过,但我希望它有所帮助。
在调查问题并详细说明选项后,我决定更改设计并为我的所有类使用一个且只有一个命名空间。理由如下:
-
类和命名空间之间的关系自然是一对一的。即使我手动模拟 XSD 以便我的实例文档正确验证,JAXB 解组器也会忽略属于不匹配的名称空间的元素,因此破解 XSD 根本无济于事。
-
我可以轻松地在多个包和编译单元上重用相同的命名空间。类路径只需要正确设置,Maven 会在使用 jaxb2-maven-plugin 时为我做。
-
我可以轻松地将所有类与一个命名空间相关联,并且每个顶级元素仍然具有不同的 XSD 文件。优点是每个输出 XSD 文件仅包含运行 schemagen 时从包含的根元素类引用的类(即复杂类型(。
进行此更改后,我得到每个编译单元一个 XSD 文件。每个编译单元只包含一个根元素(即.class(。每个根元素仅引用可通过表示根元素的类强烈访问的复杂类型。这正是我想要的。