Перезапись JAXB package-info.java: Каким должно быть «пространство имен»? - PullRequest
0 голосов
/ 07 июня 2018

Мы используем xjc для генерации Java-классов JAXB для генерации XML.Все работает отлично, за исключением того, что мы попытались настроить сгенерированные префиксы пространства имен , как описано здесь .Мы застряли с «решением 2», настраивая package-info.java, из-за используемой версии JAXB.

Структура, которую мы имеем, имеет несколько глубинных импортов: корневое пространство имен импортирует другое пространство имен, которое вочередь импортирует еще третий.

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 (импортирует третье.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>

third.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, с которым не связано никакое пространство имен, я предполагаю, потому что это внутреннийtype).

Теперь это частично вопрос: вот

сгенерированный 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 является правильным в любом случае.

Проблема исправлена, но мы хотели бы понять концепцию.Чего нам не хватает?

РЕДАКТИРОВАТЬ:

Для полноты, вот раздел build моего pom.xml:

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

1 Ответ

0 голосов
/ 07 июня 2018

Проблема в том, что вы генерируете все ваши классы в одном пакете (настроенном с помощью packageName плагина Maven.

Не делайте этого.

JAXB в некоторой степени основан наКонцепция соответствия пространства имен пакета. Для каждого используемого пространства имен должен быть один пакет. Хотя технически возможно сделать это иначе, вы будете сталкиваться с одной проблемой за другой. Поэтому лучше следовать этой концепции и использовать или сгенерировать ее.пакет на пространство имен. Вы по-прежнему можете настраивать целевые пакеты, но используя файлы привязки вместо элементов конфигурации плагина.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...