当我想用 jaxb2 生成 xsd 文件时,如何为所有 java 类指定相同的命名空间?

问题描述

我有一个 XML 文件来配置程序。 XML 配置是用 jaxb 解组的。我认为从这些类生成 XSD 文件会很有用,这样其他开发人员可以更轻松地更改设置并避免错误

可以使用没有命名空间的 XSD 文件,但 jaxb2 后处理工具将无法工作(我坚持使用名称“schema1.xsd”而无法在创建时更改它)。

您可以在下面看到如何将 XSD 文件“导入”到没有命名空间的 XML 文件中:

<roottag
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="file:///C:/path/to/the/file/schema1.xsd">
<subTags>
</subTags>
</roottag>

我发现一些博客指出应该向 @XmlRootElement 添加一个命名空间,例如 `@XmlRootElement(namespace = "myNameSpace") 但是当我的类使用其他类的实例时我该怎么办?

您可以在下面看到我的类的简化:

@XmlRootElement(name = "library")
@XmlAccessorType(XmlAccesstype.FIELD)
public class Library {
    // creates a wrapper around a List
    @XmlElementWrapper(name = "books")
    // lists this tag
    @XmlElement(name = "book")
    private List<Book> books = new ArrayList<>();

    private Address address;

    private String nameOfLibrary;
@XmlRootElement(name = "book")
@XmlAccessorType(XmlAccesstype.FIELD)
public class Book {
    private String title;
    private String author;
}
@XmlRootElement(name = "address")
@XmlAccessorType(XmlAccesstype.FIELD)
public class Address {
    private String street;
    private String town;
}

当我仅将命名空间添加到我的第一个类 (Library) 时,jaxb 会生成一个仅用于 Library.java 的 schema1.xsd 文件,该命名空间导入第二个 XSD 文件 schema2.xsd 和所有其他对象。

当我将namespcae添加到每个XmlRootElement和XmlElement时,schema2.xsd和schema1.xsd之间仍然存在分离

您可以在下方看到插件设置:

<plugins>
<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>jaxb2-maven-plugin</artifactId>
    <executions>
        <execution>
            <id>schemagen</id>
            <goals>
                <goal>schemagen</goal>
            </goals>
        </execution>
    </executions>
    <configuration>
        <sources>
            <source>src/main/java/de/soptim/za/tools/backup/checking/config</source>
        </sources>
        <outputDirectory>src/main/resources/schema</outputDirectory>
        <clearOutputDir>false</clearOutputDir>
    </configuration>
</plugin>
</plugins>
<dependencies>
<dependency>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>jaxb2-maven-plugin</artifactId>
    <version>2.5.0</version>
</dependency>

<dependency>
    <groupId>com.sun.xml.bind</groupId>
    <artifactId>jaxb-core</artifactId>
    <version>3.0.0</version>
</dependency>
</dependencies>

也许我也误解了命名空间的概念,我现在很困惑。

解决方法

我假设您的 JAXB 注释类(LibraryAddressBook)都在 一个常见的包,似乎是 de.soptim.za.tools.backup.checking.config。 然后你可以在这个包中放入一个package-info.java文件, 使用 @XmlSchema 注释包并在那里指定命名空间。

@XmlSchema(namespace = "http://mynamespace.com",elementFormDefault = XmlNsForm.QUALIFIED,attributeFormDefault = XmlNsForm.UNSET)
package de.soptim.za.tools.backup.checking.config;

import javax.xml.bind.annotation.XmlNsForm;
import javax.xml.bind.annotation.XmlSchema;

另见 API doc of @XmlSchema 和此 related question

对于编组/解组,这个命名空间将适用于所有 你那个包的 JAXB 类 (当然,您显式设置另一个命名空间除外 任何个人 @XmlElement@XmlElementWrapper@XmlAttribute@XmlRootElement 类中的注释)。

当从这个包的类生成模式时 你应该只生成一个 XSD 文件, 因为你的类只使用一个命名空间。