我想通过 Javafx 添加 Schema 注释到包中-info.java

I want to add a Schema annotation via Javafx to the package-info.java

所以我有一个特定的 Schema 注释需要添加到包中-info.java。我尝试了一些方法并在线搜索了答案,但找不到任何适用于我的问题的答案。

packag-info.java:

@javax.xml.bind.annotation.XmlSchema(
          ...
        )
package my.package.name;

我想要的 XmlSchema:

<databaseChangeLog
    xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog-ext 
        http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd http://www.liquibase.org/xml/ns/pro
        http://www.liquibase.org/xml/ns/pro/liquibase-pro-4.1.xsd http://www.liquibase.org/xml/ns/dbchangelog 
        http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.1.xsd">
</databaseChangeLog>

我的问题是,@javax.xml.bind.annotation.XmlSchema(...) 中必须包含什么才能实现此架构?

对于遇到类似问题的任何人,我找到了解决方案。

此处的架构有两个组件,必须在您的代码中设置才能生成,

命名空间:

xmlns="http://www.liquibase.org/xml/ns/dbchangelog"

架构位置:

xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog-ext 
        http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd http://www.liquibase.org/xml/ns/pro
        http://www.liquibase.org/xml/ns/pro/liquibase-pro-4.1.xsd http://www.liquibase.org/xml/ns/dbchangelog 
        http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.1.xsd"

必须使用 javax

package-info.java 中设置 namespace
@javax.xml.bind.annotation.XmlSchema(
            namespace = "http://www.liquibase.org/xml/ns/dbchangelog",
            elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
package de.softproject.x4.server.migration.keycloak.changelog_beans;

但是schemaLocation不能在这里设置,或者至少我还没有找到如何设置。有效的是直接用 jaxb 设置它(我使用 jaxb 作为我的 Java XML 绑定框架,如果你使用另一个,这个解决方案将不适用)

JAXBContext jaxbContext = JAXBContext.newInstance(ClassToHaveSchema.class);
Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.setProperty(Marshaller.JAXB_SCHEMA_LOCATION, 
                    "http://www.liquibase.org/xml/ns/dbchangelog-ext 
                     http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog- 
                               ext.xsd http://www.liquibase.org/xml/ns/pro
                     http://www.liquibase.org/xml/ns/pro/liquibase-pro-4.1.xsd 
                     http://www.liquibase.org/xml/ns/dbchangelog 
                     http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog- 
                             4.1.xsd"); 

这里的重要部分是 marshaller.setProperty(Marshallar.JAXB_SCHEMA_LOCATION, ...)。当您使用要编组的 class 设置 JAXB 编组器时,这将添加您指定的 xsi:schemaLocation 并自动为您生成 xmlns:xsi(标准名称空间前缀 xsi)

结果 XML 的模式设置如下:

<ClassToHaveSchema
    xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog-ext 
        http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd http://www.liquibase.org/xml/ns/pro
        http://www.liquibase.org/xml/ns/pro/liquibase-pro-4.1.xsd http://www.liquibase.org/xml/ns/dbchangelog 
        http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.1.xsd">
</ClassToHaveSchema>

您的 SchemaLocation 可能比此处更短或更长,它不一定要长 6 个 URI,但在本例中就是这样。

您当然可以创建一个 class 包含此信息作为常量:

public class LiquibaseInfo {

    public static final String NAMESPACE = "http://www.liquibase.org/xml/ns/dbchangelog";
    public static final String SCHEMA_LOCATION = "http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd http://www.liquibase.org/xml/ns/pro http://www.liquibase.org/xml/ns/pro/liquibase-pro-4.1.xsd http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.1.xsd";

    private LiquibaseInfo() {}
}

然后在你的代码中使用常量,这样会更容易理解:

...
namespace = LiquibaseInfo.NAMESPACE
...

...
marshaller.setProperty(Marshaller.JAXB_SCHEMA_LOCATION, LiquibaseInfo.SCHEMA_LOCATION);
...

注意: 当在 package-info 中设置 namespace 时,这个包现在链接到这个 namespace。意思是,如果你在这个包中的一些 class 中解组一些 XML 文件,它使用另一个 namespace,它将不起作用,因为它需要集合 namespace。发生在我身上,可以通过更好地更改包轻松修复,但你不必考虑你的代码不起作用。