【问题标题】:JAXB Overwriting package-info.java: What should be "namespace"?JAXB 覆盖 package-info.java:“命名空间”应该是什么?
【发布时间】:2018-11-17 10:40:14
【问题描述】:

我们使用 xjc 来生成用于 XML 生成的 JAXB Java 类。除了我们尝试调整生成的命名空间前缀as described here 之外,一切正常。由于我们使用的 JAXB 版本,我们坚持使用“解决方案 2”,调整 package-info.java。

我们的结构是几个深度导入:根命名空间导入其他命名空间,而后者又导入第三个命名空间。

MCVE xsds

root.xsd(导入 other.xsd):

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="root" xmlns:other="other" targetNamespace="root" version="1.0">
    <xs:import namespace="other" schemaLocation="other.xsd" />
    <xs:element name="rootElem">
        <xs:complexType>
            <xs:choice>
                <xs:element ref="rootElem1"/>
            </xs:choice>
        </xs:complexType>
    </xs:element>
    <xs:element name="rootElem1" nillable="false">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="data">
                    <xs:complexType>
                        <xs:choice>
                            <xs:element ref="other:otherElem"/>
                        </xs:choice>
                    </xs:complexType>
                </xs:element>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
    </xs:schema>

other.xsd(导入third.xsd):

<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:other="other" xmlns:third="third" targetNamespace="other" elementFormDefault="qualified" attributeFormDefault="unqualified" version="1.0">
<xsd:import namespace="third" schemaLocation="third.xsd" />
    <xsd:element name="otherElem">
        <xsd:complexType>
            <xsd:sequence>
                <xsd:element ref="third:thirdElem" />
            </xsd:sequence>
        </xsd:complexType>
    </xsd:element>
</xsd:schema>

第三个.xsd:

<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:third="third" targetNamespace="third" elementFormDefault="qualified" attributeFormDefault="unqualified" version="1.0">
    <xsd:element name="thirdElem">
        <xsd:complexType>
            <xsd:sequence>
                <xsd:element name="thirdData" type="xsd:string" />
            </xsd:sequence>
        </xsd:complexType>
    </xsd:element>
</xsd:schema>

有了这个

简单的测试用例

@Test
public void test() throws JAXBException
{
    Marshaller marshaller = JAXBContext.newInstance("test.jaxb.generated").createMarshaller();
    marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
    marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
    marshaller.setProperty(Marshaller.JAXB_SCHEMA_LOCATION, "http://www.example.com/schema.xsd");

    RootElem root = new RootElem();
    RootElem1 root1 = new RootElem1();
    Data d = new Data();
    OtherElem other = new OtherElem();
    ThirdElem thirdElem = new ThirdElem();
    thirdElem.setThirdData("third");
    other.setThirdElem(thirdElem);
    d.setOtherElem(other);
    root1.setData(d);
    root.setRootElem1(root1);

    Path path = Paths.get("target", "outfile.xml");

    Result result = new StreamResult(path.toFile());
    marshaller.marshal(root, result);
}

这导致了这个

生成的 XML

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns4:rootElem xmlns:ns2="other" xmlns:ns3="third" xmlns:ns4="root" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.example.com/schema.xsd">
    <ns4:rootElem1>
        <data>
            <ns2:otherElem>
                <ns3:thirdElem>
                    <ns3:thirdData>third</ns3:thirdData>
                </ns3:thirdElem>
            </ns2:otherElem>
        </data>
    </ns4:rootElem1>
</ns4:rootElem>

一切都很好(除了data,它没有关联任何命名空间,我假设这是一个内部类型)。

现在这是部分问题:这是

生成的 package-info.java

@javax.xml.bind.annotation.XmlSchema(namespace = "other", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
package test.jaxb.generated;

为什么namespace 指的是other?我的根命名空间是root。 (root.xsd 是我们提供给 Maven 的唯一文件jaxb2-maven-plugin;我们可以包含其他文件,这没有区别)。

错误替换 package-info.java

如果我们用这个覆盖生成的:

@javax.xml.bind.annotation.XmlSchema(
        namespace = "root",
        xmlns = {
                @javax.xml.bind.annotation.XmlNs(prefix = "t", namespaceURI = "third"),
                @javax.xml.bind.annotation.XmlNs(prefix = "o", namespaceURI = "other"),
                @javax.xml.bind.annotation.XmlNs(prefix = "r", namespaceURI = "root")
        },
        elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
package test.jaxb.generated;

我们最初这样做是因为我们假设我们必须在这里给出根命名空间 - 这是

生成的 XML 错误

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<r:rootElem xmlns:t="third" xmlns:o="other" xmlns:r="root" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.example.com/schema.xsd">
    <r:rootElem1>
        <data>
            <r:otherElem>
                <t:thirdElem>
                    <t:thirdData>third</t:thirdData>
                </t:thirdElem>
            </r:otherElem>
        </data>
    </r:rootElem1>
</r:rootElem>

现在命名空间很漂亮,但是错了! otherElem 属于 o,而不是 r

将覆盖文件中的命名空间改回other 可修复错误,但又一次:

问题是为什么这里需要命名空间other?同样令人困惑的是,third 导入的层无论哪种方式都是正确的。

问题已解决,但我们想了解这个概念。我们缺少什么?

编辑:

为了完整起见,这是我的pom.xmlbuild 部分:

<build>
    <plugins>
        <plugin>
        <!-- run xjc -->
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>jaxb2-maven-plugin</artifactId>
            <executions>
                <execution>
                    <id>xjc-generate_classes</id>
                    <goals>
                        <goal>xjc</goal>
                    </goals>
                    <configuration>
                        <packageName>test.jaxb.generated</packageName>
                        <schemaFiles>
                            root.xsd
                        </schemaFiles>
                        <schemaDirectory>${basedir}/src/main/resources/schemata</schemaDirectory>
                        <extension>true</extension>
                        <bindingDirectory>${basedir}/src/main/resources/bindings</bindingDirectory>
                        <outputDirectory>${basedir}/target/generated-sources/jaxb/</outputDirectory>
                    </configuration>
                </execution>
            </executions>
        </plugin>
        <!-- overwrite created package-info.java -->
         <plugin>
            <artifactId>maven-resources-plugin</artifactId>
            <executions>
                <execution>
                    <id>copy-resources</id>
                    <phase>process-resources</phase>
                    <goals>
                        <goal>copy-resources</goal>
                    </goals>
                    <configuration>
                        <overwrite>true</overwrite>
                        <outputDirectory>${basedir}/target/generated-sources/jaxb/test/jaxb/generated</outputDirectory>
                        <resources>
                            <resource>
                                <directory>${basedir}/src/main/resources/bindings</directory>
                                <include>package-info.java</include>
                            </resource>
                        </resources>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

【问题讨论】:

  • 如何将test.jaxb.generated配置为目标包?
  • @lexicore 在 pom.xml 中。我将其添加到帖子中。

标签: java xml jaxb


【解决方案1】:

问题是您在一个包中生成所有类(使用 Maven 插件的packageName 配置。

不要这样做。

JAXB 在某种程度上基于包命名空间对应的概念。您使用的每个命名空间应该有一个包。虽然在技术上可以这样做,但您将面临一个接一个的问题。所以最好遵循这个概念,每个命名空间使用或生成一个包。您仍然可以配置目标包 - 但使用绑定文件而不是插件配置元素。

【讨论】:

  • 但是如何配置它只生成我需要的一个包呢? pom.xml 中给出的 root.xsd 已经吸收了导入的模式并从中生成代码。我确实尝试单独生成导入的代码,但这只会导致代码没有被使用(因为root.xsd 生成的代码只使用它自己生成的类xjc 运行)。如果我设法限制包 - root 类将如何知道他们需要导入的包?
  • @daniu 不确定您的问题是什么。你应该在这里生成三个包,而不是一个。 root.xsd 导入其他模式并不重要。您可以使用绑定自定义每个模式的目标包。我真的没有看到问题。
  • @daniu 如果你想为命名空间指定包,是的,推荐的方式是使用bindings.xjb。在插件中只需删除 packageName 配置元素(我猜是这样)。您不需要在pom.xml 中配置单独的包(您不能),您可以在bindings.xjb 中进行配置。
  • @daniu 这是example。寻找jaxb:schemaBindingsjaxb:package,其余无关紧要。
  • @daniu 通过一些分析可以发现这一点。但在我看来,这不值得。
猜你喜欢
  • 1970-01-01
  • 2011-11-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-25
  • 1970-01-01
  • 1970-01-01
  • 2014-04-01
相关资源
最近更新 更多